Inteligencia Artificial

LangChain vs LangGraph: ¿Qué Framework Elegir para tu Agente Autónomo?

Comparativa técnica detallada de los frameworks más populares para desarrollo de agentes autónomos. Código de ejemplo, casos de uso y recomendaciones.

Equipo Nexgen
7 min de lectura
#IA#Agentes Autónomos#LangChain#LangGraph#LLM#Python
LangChain vs LangGraph: ¿Qué Framework Elegir para tu Agente Autónomo?

El desarrollo de agentes autónomos con IA está en pleno auge. Dos frameworks dominan el ecosistema: LangChain y LangGraph. En esta guía, exploraremos sus diferencias, ventajas y cuándo usar cada uno.

¿Qué es LangChain?

LangChain es un framework de código abierto para construir aplicaciones con modelos de lenguaje (LLMs). Proporciona abstracciones de alto nivel para tareas comunes como:

  • Chains: Secuencias predefinidas de llamadas al LLM
  • Agents: Entidades que pueden usar herramientas y tomar decisiones
  • Memory: Sistemas de almacenamiento de conversaciones
  • Tools: Interfaces para que los agentes ejecuten acciones

Ejemplo Básico de LangChain

from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.llms import OpenAI
from langchain.memory import ConversationBufferMemory

# Definir herramientas
def search_web(query: str) -> str:
    # Implementación de búsqueda web
    return f"Resultados para: {query}"

tools = [
    Tool(
        name="WebSearch",
        func=search_web,
        description="Busca información en la web"
    )
]

# Inicializar LLM
llm = OpenAI(temperature=0)

# Crear memoria
memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True
)

# Inicializar agente
agent = initialize_agent(
    tools=tools,
    llm=llm,
    agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,
    memory=memory,
    verbose=True
)

# Ejecutar
response = agent.run("¿Cuál es el clima en México hoy?")
print(response)

¿Qué es LangGraph?

LangGraph es una extensión de LangChain que añade gestión de estado explícita y ciclos de ejecución. Está construido sobre el concepto de grafos de estado, donde los agentes pueden:

  • Mantener estado persistente entre ejecuciones
  • Implementar ciclos complejos (loops, branches)
  • Ejecutar pasos condicionales basados en resultados previos
  • Hacer rollback a estados anteriores

Ejemplo Básico de LangGraph

from langgraph.graph import StateGraph, END
from langchain.chat_models import ChatOpenAI
from typing import TypedDict

# Definir el estado
class AgentState(TypedDict):
    messages: list
    current_step: str
    result: str

# Definir funciones de nodos
def call_llm(state: AgentState) -> AgentState:
    llm = ChatOpenAI()
    response = llm.predict(state["messages"][-1])
    state["messages"].append(response)
    return state

def should_continue(state: AgentState) -> str:
    if "final" in state["messages"][-1].lower():
        return "end"
    return "continue"

# Construir el grafo
workflow = StateGraph(AgentState)

# Agregar nodos
workflow.add_node("llm", call_llm)
workflow.add_node("continue", call_llm)

# Agregar edges
workflow.add_edge("llm", "continue")
workflow.add_conditional_edges(
    "continue",
    should_continue,
    {
        "continue": "llm",
        "end": END
    }
)

# Configurar entrada
workflow.set_entry_point("llm")

# Compilar
app = workflow.compile()

# Ejecutar
result = app.invoke({
    "messages": ["Analiza el mercado de SaaS"],
    "current_step": "start",
    "result": ""
})

Comparativa Técnica Detallada

1. Arquitectura y Diseño

LangChain:

  • Arquitectura lineal o ramificada simple
  • Chains predefinidos para casos comunes
  • Agentes basados en ReAct pattern
  • Ejecución secuencial de pasos

LangGraph:

  • Arquitectura basada en grafos de estado
  • Control de flujo explícito y complejo
  • Permite ciclos y retroalimentación
  • Estado persistente entre nodos

2. Gestión de Estado

# LangChain - Estado implícito en memoria
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
memory.save_context(
    {"input": "Pregunta"},
    {"output": "Respuesta"}
)

# LangGraph - Estado explícito tipado
from typing import TypedDict

class State(TypedDict):
    messages: list
    context: dict
    tools_called: list
    iterations: int

Ventaja de LangGraph: Estado explícito permite debugging más sencillo y comportamiento más predecible.

3. Control de Flujo

# LangChain - Control limitado
agent.run("Ejecuta esta tarea")  # El agente decide internamente

# LangGraph - Control granular
workflow.add_conditional_edges(
    "node_a",
    lambda state: "success" if state["score"] > 0.8 else "retry",
    {
        "success": "node_b",
        "retry": "node_a"  # Loop back
    }
)

4. Casos de Uso Óptimos

| Característica | LangChain | LangGraph | |---------------|-----------|-----------| | Chatbots simples | ✅ Excelente | ⚠️ Overkill | | RAG (Q&A) | ✅ Excelente | ✅ Bueno | | Agentes con herramientas | ✅ Muy bueno | ✅ Excelente | | Workflows complejos | ⚠️ Limitado | ✅ Excelente | | Sistemas con estado | ⚠️ Básico | ✅ Excelente | | Debugging | ⚠️ Difícil | ✅ Más sencillo | | Curva de aprendizaje | ✅ Suave | ⚠️ Más empinada |

Implementación Real: Agente de Análisis de Datos

Veamos un caso real comparando ambos frameworks:

Con LangChain

from langchain.agents import create_pandas_dataframe_agent
from langchain.llms import OpenAI
import pandas as pd

# Cargar datos
df = pd.read_csv("ventas.csv")

# Crear agente
agent = create_pandas_dataframe_agent(
    OpenAI(temperature=0),
    df,
    verbose=True
)

# Ejecutar análisis
result = agent.run("""
    Analiza las ventas del último trimestre y proporciona:
    1. Total de ventas
    2. Producto más vendido
    3. Tendencia general
""")

print(result)

Limitaciones:

  • Difícil agregar validación personalizada
  • No hay control sobre pasos intermedios
  • Estado limitado a la memoria del conversation buffer

Con LangGraph

from langgraph.graph import StateGraph, END
from langchain.chat_models import ChatOpenAI
from typing import TypedDict
import pandas as pd

class AnalysisState(TypedDict):
    data: pd.DataFrame
    query: str
    analysis_steps: list
    results: dict
    validation_passed: bool

def validate_data(state: AnalysisState) -> AnalysisState:
    """Valida que los datos sean correctos"""
    df = state["data"]
    if df.empty:
        raise ValueError("DataFrame vacío")
    state["validation_passed"] = True
    return state

def analyze_sales(state: AnalysisState) -> AnalysisState:
    """Analiza las ventas"""
    df = state["data"]

    # Análisis
    total_sales = df["amount"].sum()
    top_product = df.groupby("product")["amount"].sum().idxmax()

    state["results"] = {
        "total_sales": total_sales,
        "top_product": top_product
    }
    state["analysis_steps"].append("sales_analyzed")
    return state

def generate_insights(state: AnalysisState) -> AnalysisState:
    """Genera insights con LLM"""
    llm = ChatOpenAI()

    prompt = f"""
    Basándote en estos datos:
    - Ventas totales: {state["results"]["total_sales"]}
    - Producto top: {state["results"]["top_product"]}

    Genera insights y recomendaciones.
    """

    insights = llm.predict(prompt)
    state["results"]["insights"] = insights
    state["analysis_steps"].append("insights_generated")
    return state

def should_retry(state: AnalysisState) -> str:
    """Decide si necesita más análisis"""
    if len(state["analysis_steps"]) < 3:
        return "continue"
    return "end"

# Construir workflow
workflow = StateGraph(AnalysisState)

workflow.add_node("validate", validate_data)
workflow.add_node("analyze", analyze_sales)
workflow.add_node("insights", generate_insights)

workflow.set_entry_point("validate")
workflow.add_edge("validate", "analyze")
workflow.add_edge("analyze", "insights")

workflow.add_conditional_edges(
    "insights",
    should_retry,
    {
        "continue": "analyze",  # Puede hacer más análisis
        "end": END
    }
)

# Compilar y ejecutar
app = workflow.compile()
result = app.invoke({
    "data": pd.read_csv("ventas.csv"),
    "query": "Analiza ventas Q4 2025",
    "analysis_steps": [],
    "results": {},
    "validation_passed": False
})

print(result["results"])

Ventajas de LangGraph:

  • Validación explícita en cada paso
  • Puede reintentar análisis si es necesario
  • Estado completamente trazable
  • Fácil agregar nuevos pasos

Debugging y Observabilidad

LangChain

# Activar verbose mode
agent = initialize_agent(
    tools=tools,
    llm=llm,
    verbose=True  # Imprime cada paso
)

# Callbacks personalizados
from langchain.callbacks import StdOutCallbackHandler

handler = StdOutCallbackHandler()
agent.run("Query", callbacks=[handler])

LangGraph

# Inspeccionar estado en cada paso
def debug_node(state: AgentState) -> AgentState:
    print(f"Estado actual: {state}")
    return state

workflow.add_node("debug", debug_node)

# Visualizar el grafo
from langchain.graphs import graph
graph.visualize(app)  # Genera diagrama del flujo

Rendimiento y Escalabilidad

Latencia

LangChain:

  • Overhead mínimo para casos simples
  • Latencia aumenta con complejidad de chains

LangGraph:

  • Overhead adicional por gestión de estado
  • Mejor para workflows de larga duración

Caching

# LangChain - Cache de LLM
from langchain.cache import InMemoryCache
import langchain
langchain.llm_cache = InMemoryCache()

# LangGraph - Cache de estado
from langgraph.checkpoint import MemorySaver

checkpointer = MemorySaver()
app = workflow.compile(checkpointer=checkpointer)

# Permite reanudar desde cualquier punto
result = app.invoke(state, config={"thread_id": "user_123"})

Cuándo Usar Cada Uno

Usa LangChain si:

✅ Construyes un chatbot Q&A simple ✅ Implementas RAG básico ✅ Necesitas prototipo rápido ✅ No requieres control fino del flujo ✅ Tu equipo es nuevo en LLMs

Usa LangGraph si:

✅ Construyes agentes complejos con múltiples herramientas ✅ Necesitas workflows con ciclos y condiciones ✅ Requieres debugging detallado ✅ El estado entre ejecuciones es crítico ✅ Construyes sistemas de producción robustos

Mejor Práctica: Enfoque Híbrido

En muchos proyectos, lo mejor es combinar ambos:

# Usa LangChain para componentes individuales
from langchain.tools import Tool
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI()

# Usa LangGraph para orquestar el flujo
from langgraph.graph import StateGraph

workflow = StateGraph(AgentState)

def use_langchain_tool(state: AgentState) -> AgentState:
    # Aprovecha las herramientas de LangChain
    tool = Tool(...)
    result = tool.run(state["query"])
    state["result"] = result
    return state

workflow.add_node("tool", use_langchain_tool)

Migración de LangChain a LangGraph

Si ya tienes código en LangChain y quieres migrar:

# Antes (LangChain)
from langchain.agents import initialize_agent

agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
result = agent.run("Query")

# Después (LangGraph)
from langgraph.prebuilt import create_react_agent

app = create_react_agent(llm, tools)
result = app.invoke({"messages": [("user", "Query")]})

Conclusión

LangChain es perfecto para comenzar y para casos de uso straightforward. LangGraph brilla cuando necesitas control preciso, workflows complejos y sistemas de producción robustos.

En Nexgen, típicamente comenzamos con LangChain para MVPs y migramos a LangGraph cuando los requisitos de complejidad y control aumentan.

¿Estás construyendo agentes autónomos? Contáctanos para una consulta técnica gratuita sobre qué framework se ajusta mejor a tu caso de uso.