El interés de búsqueda cuenta una historia bastante consistente ahora mismo: LangChain está cayendo mientras LangGraph, CrewAI y Pydantic AI suben. Eso no es un problema de marca ni un ciclo de hype quedándose sin aire — es lo que se ve cuando la abstracción central de un framework deja de encajar con el problema que realmente tienen quienes construyen. LangChain ganó la primera ola del boom de las aplicaciones LLM haciendo trivial “llamar a un modelo, encadenar unos pasos, quizá buscar en un vector store.” Los agentes en producción son otro problema: estado que tiene que sobrevivir a una caída, varios agentes que necesitan pasarse trabajo entre sí, y una sesión de depuración que tiene que mostrarte exactamente qué paso salió mal y por qué. De esa brecha va este reacomodo.
El error habitual al cubrir este tema es plantearlo como un concurso de popularidad — LangGraph “ganando,” LangChain “perdiendo.” Ese no es el enfoque útil. El enfoque útil es arquitectónico: qué asume cada framework sobre cómo se ejecuta tu agente, y si ese supuesto sigue sosteniéndose una vez que pasaste del demo a un sistema del que dependen otras personas. Este post recorre eso, apoyado en haber construido de verdad sobre ambos stacks, no en perseguir tendencias.
Aprenderás:
- Qué hizo bien LangChain y por qué se convirtió en el framework de agentes por defecto
- Los problemas concretos de LangChain en producción — gestión de estado, depuración opaca, coordinación multiagente — que empujan a los equipos a migrar
- Qué cambia LangGraph realmente a nivel estructural: grafos de estado, checkpointers y ejecuciones reanudables
- En qué se diferencian
AgentExecutory unStateGraphde LangGraph a nivel de código, lado a lado - Dónde encajan CrewAI y Pydantic AI en este mismo cambio, y por qué no son intercambiables con LangGraph
- Cuándo LangChain sigue siendo la elección correcta y cuándo una migración a LangGraph justifica la reescritura
- Cómo migrar de LangChain a LangGraph de forma incremental en lugar de todo de golpe
Tabla de contenido
- Qué hizo bien LangChain y por qué se volvió el estándar
- Dónde duele LangChain en producción: estado, depuración y churn
- Qué cambia LangGraph realmente: grafos de estado y checkpoints
- AgentExecutor vs. StateGraph de LangGraph: el código lado a lado
- CrewAI vs. LangGraph vs. Pydantic AI: qué resuelve cada uno
- Los tres puntos de dolor detrás de la migración de LangChain
- Cuándo LangChain sigue siendo la elección correcta
- Cuándo migrar a LangGraph justifica la reescritura
- Cómo migrar de LangChain a LangGraph de forma incremental
Qué hizo bien LangChain y por qué se volvió el estándar
Vale la pena ser honesto sobre por qué LangChain se convirtió en el framework de agentes por defecto, porque la historia de la migración solo tiene sentido en contraste con eso. Antes de LangChain, cada equipo que construía sobre una API de LLM escribía el mismo boilerplate desde cero: plantillas de prompts, lógica de reintentos alrededor de los rate limits, un wrapper fino sobre un vector store, alguna manera improvisada de meter el contexto recuperado dentro de un prompt. LangChain empaquetó todo eso en piezas componibles — LLMChain, retrievers, document loaders, output parsers — y trajo integraciones para prácticamente todo proveedor de modelos y toda base de datos vectorial que existía. Para la primera ola de chatbots RAG y agentes sencillos con herramientas, ese era exactamente el trade-off correcto: no necesitabas pensar en arquitectura, necesitabas entregar un demo funcionando para el viernes, y LangChain te llevaba ahí.
La abstracción AgentExecutor extendió esa misma idea a los agentes: dale al modelo una lista de herramientas, déjalo razonar en un bucle, parsea su salida, llama a la herramienta, devuélvele el resultado. Para un solo agente haciendo un puñado de llamadas a herramientas en una secuencia mayormente lineal, esto funciona bien y sigue funcionando. Una enorme cantidad de tráfico de producción legítimo tiene exactamente esa forma, y no hay razón para migrar un sistema que encaja en ella.
Dónde duele LangChain en producción: estado, depuración y churn
El problema aparece en cuanto el sistema deja de ser una línea recta, y es el mismo problema que convierte un pipeline RAG que funciona en el demo en uno que falla en producción. El bucle de AgentExecutor es una caja negra: le pasas un prompt y una lista de herramientas, y él gestiona internamente el bucle de razonamiento, los pasos intermedios y cuándo parar. Eso es cómodo justo hasta que algo sale mal a las 2 de la mañana y necesitas saber exactamente qué llamada a herramienta hizo el agente, con qué argumentos, a partir de qué razonamiento intermedio, y por qué decidió hacer una cuarta llamada en vez de detenerse en la tercera. El sistema de callbacks de LangChain puede sacar esto a la superficie, pero está atornillado a posteriori — estás reconstruyendo una historia a partir de líneas de log en lugar de leerla de una máquina de estados explícita.
El estado es el segundo punto de dolor, más agudo. Las abstracciones de memoria de LangChain se construyeron alrededor del historial conversacional — una lista de mensajes que crece. Ese no es el mismo problema que el estado de un agente: qué subtareas están hechas, qué devolvió un subagente, cómo queda el plan después de que el paso tres falló y hubo que reintentarlo con otros parámetros. Tampoco es el mismo problema que una memoria duradera que persiste entre sesiones de agentes, que es una tercera cosa distinta. Los equipos terminan atornillando una base de datos, un hash de Redis o un dict de estado hecho a mano al costado de la chain para llevar la cuenta de esto, lo que significa que el estado real de la ejecución del agente vive en parte en los objetos de LangChain y en parte en código que escribiste para compensar lo que LangChain no rastrea. En esa división es donde viven los bugs.
La coordinación multiagente es el tercer punto de presión, y es el que los datos de búsqueda reflejan con más claridad. En el momento en que necesitas que dos o más agentes se pasen trabajo — un planificador que delega en un investigador, un investigador que entrega hallazgos verificados a un redactor — AgentExecutor no tiene un concepto nativo de eso. Vuelves a escribir tu propia capa de orquestación sobre un framework cuya propuesta de valor entera se suponía que era “no tienes que escribir eso.”
Hay un cuarto punto de dolor más silencioso que agrava a los otros tres: el propio churn de LangChain. La librería ha pasado por suficientes reorganizaciones incompatibles — rutas de módulos que se mueven, subclases de Chain marcadas como obsoletas en favor de LCEL (LangChain Expression Language), y luego LCEL mismo quedando algo incómodo junto a las APIs de agentes más nuevas — como para que los equipos con un sistema en producción sobre una versión antigua enfrenten una elección real entre actualizar a través de varios cambios incompatibles o quedarse pinneados indefinidamente. Un framework que todavía está rediseñando activamente sus propias abstracciones centrales es una base más difícil para un sistema de producción estable que uno que ya se asentó, y esa inestabilidad es en sí misma la razón por la que algunos equipos deciden que migrar a un stack más nuevo y aparentemente más estable es menos riesgo que seguir en la cinta de versiones de LangChain.
Qué cambia LangGraph realmente: grafos de estado y checkpoints
El pitch de LangGraph no es “LangChain pero más nuevo.” Es una idea estructuralmente distinta: tu agente es un grafo de estado, no un bucle opaco. Defines nodos — unidades de trabajo, que pueden ser una llamada a un LLM, una llamada a una herramienta o Python arbitrario — y aristas entre ellos, incluidas aristas condicionales que enrutan según el estado actual. El estado en sí es un objeto explícito y tipado que fluye por el grafo y se actualiza en cada nodo. Ese único cambio resuelve los dos mayores puntos de dolor de LangChain a la vez.
La depuración mejora porque el grafo es inspeccionable por construcción. Puedes trazar una ejecución nodo por nodo y ver el estado exacto en cada punto, no reconstruirlo a partir de logs de callbacks. El checkpointer de LangGraph lleva esto más lejos: persiste el estado después de cada nodo, lo que significa que una ejecución que se cae puede reanudarse desde su último checkpoint en vez de empezar de cero, y puedes literalmente reproducir las transiciones de estado de una ejecución pasada para ver qué pasó. Esa es la diferencia entre “añade logging y ojalá alcance” y “el framework se construyó asumiendo que ibas a necesitar inspeccionar esto.”
La coordinación multiagente deja de ser algo que atornillas, porque un grafo se presta naturalmente a ello: cada agente es un subgrafo o un nodo, y el objeto de estado compartido es el mecanismo de entrega. Un nodo planificador escribe un plan en el estado; un nodo investigador lo lee, hace su trabajo y escribe los hallazgos de vuelta; una arista enrutadora decide quién corre después según lo que hay en el estado. Este es el mecanismo real, no una descripción de marketing — es por lo que LangGraph aparece como la respuesta por defecto cuando la gente pregunta cómo construir un sistema multiagente sobre el ecosistema de LangChain.
El trade-off es real, eso sí: LangGraph es más explícito, lo que significa más código por adelantado para un caso simple. Un chatbot de un solo agente que responde preguntas sobre una base de conocimiento no necesita un grafo de estado. Escribirle uno es sobreingeniería, no arquitectura.
AgentExecutor vs. StateGraph de LangGraph: el código lado a lado
Es más fácil ver la diferencia real que describirla. Un bucle de agente de LangChain es una sola llamada que esconde los pasos de razonamiento dentro del executor:
from langchain.agents import AgentExecutor, create_tool_calling_agent
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({"input": "Find the latest invoice and flag anomalies"})
Todo lo que ocurre entre “input” y “result” — cuántas llamadas a herramientas hubo, en qué orden, sobre qué razonamiento intermedio — vive dentro de las tripas del executor. verbose=True te da un flujo de logs, no un estado consultable.
Una versión con LangGraph convierte ese bucle de razonamiento en un grafo que defines tú:
from langgraph.graph import StateGraph, END
def call_model(state: AgentState) -> AgentState:
response = llm.invoke(state["messages"])
return {"messages": [response]}
def route(state: AgentState) -> str:
last = state["messages"][-1]
return "tools" if last.tool_calls else END
graph = StateGraph(AgentState)
graph.add_node("agent", call_model)
graph.add_node("tools", tool_node)
graph.add_conditional_edges("agent", route, {"tools": "tools", END: END})
graph.add_edge("tools", "agent")
app = graph.compile(checkpointer=checkpointer)
Aquí no hay nada oculto. state es un objeto tipado que definiste tú, cada nodo es una función corriente que puedes testear de forma aislada, y route es exactamente la lógica de decisión que antes vivía dentro de la caja negra del executor. El argumento checkpointer es lo que compra la reanudabilidad: app.compile(checkpointer=checkpointer) persiste state después de que corre cada nodo, de modo que app.invoke puede retomar una ejecución caída desde su último nodo completado en lugar de rehacerlo todo. Esa es la diferencia estructural que describe el resto de este post — no una función nueva atornillada al modelo viejo, sino un modelo distinto.
El grafo explícito es además donde los controles operativos por fin tienen dónde vivir. Una vez que el enrutamiento es una función y el estado es un objeto, un kill switch para el agente y permisos de herramientas acotados pasan a ser un nodo y una arista, en lugar de un wrapper del que esperas que envuelva todo.
CrewAI vs. LangGraph vs. Pydantic AI: qué resuelve cada uno
CrewAI y Pydantic AI suben en los mismos datos de búsqueda, pero resuelven problemas adyacentes, no el mismo, y confundirlos con LangGraph es un error común.
CrewAI se sitúa un nivel por encima de LangGraph. En vez de que tú definas nodos y aristas, defines roles — un agente “investigador,” un agente “redactor,” un agente “editor” — cada uno con un objetivo y una historia de fondo, y CrewAI se encarga de la delegación y la secuencia entre ellos. Es la herramienta correcta cuando tu sistema multiagente se mapea de forma natural sobre una metáfora de equipo y quieres que esa orquestación te la resuelvan. El costo es el mismo que tenía el AgentExecutor de LangChain: menos visibilidad sobre cómo ocurre exactamente la delegación, porque CrewAI es dueño de esa lógica internamente.
Pydantic AI es otro tipo de reacción a la misma queja de fondo. No va de orquestación en absoluto — va de seguridad de tipos y de minimizar la magia. Donde LangChain e incluso LangGraph pueden dejarte pasando dicts poco tipados por tu pipeline, Pydantic AI se apoya en modelos de Pydantic para entradas y salidas estructuradas en cada frontera: la salida del agente es un modelo validado, no un string que esperas que sea JSON. Para ingenieros de backend que ya piensan en términos de esquemas y quieren un framework de agentes que se comporte como el resto de su codebase tipada en lugar de introducir un mundo paralelo sin tipos, ese es el verdadero atractivo — no una historia de orquestación rival, sino una filosofía rival sobre cuánto debería inferir el framework y cuánto deberías declarar tú.
Vale la pena señalar que ninguno de estos tres es dueño de la capa de herramientas como lo es de la orquestación. Las herramientas llegan cada vez más por MCP, el Model Context Protocol, que los tres pueden consumir — así que “qué framework” y “qué herramientas” son decisiones separadas, y elegir uno no ata al otro.
Los tres puntos de dolor detrás de la migración de LangChain
Despojados de nombres de frameworks, hay tres problemas concretos de producción impulsando todo este cambio. Primero, la opacidad al depurar: cuando algo sale mal en el razonamiento de un agente, cuánto tardas en averiguar por qué, y el framework te da una traza de estado o un montón de líneas de log para reconstruir a mano. Segundo, la reanudabilidad: si un proceso de agente de larga duración muere a mitad de la tarea, ¿arranca desde cero o desde donde se quedó?, y ¿puedes responder esa pregunta sin leer las tripas del framework? Tercero, la coordinación: cuando necesitas más de un agente, ¿te da el framework una primitiva real para la entrega de estado, o escribes esa capa tú mismo sobre una abstracción que asumió un único agente todo el tiempo?
Todo equipo que migra de LangChain a LangGraph, CrewAI o Pydantic AI está respondiendo una de esas tres preguntas con “el stack viejo hacía esto más difícil de lo necesario.” Esa es la señal real en los datos de búsqueda — no hype, sino una acumulación real de fricción de producción que una arquitectura nueva ataca directamente.
Cuándo LangChain sigue siendo la elección correcta
No reescribas un sistema que no está sufriendo. Si estás corriendo un solo agente por una secuencia de pasos mayormente lineal — recuperar, razonar, responder, quizá llamar a una o dos herramientas — AgentExecutor sigue haciendo ese trabajo bien, y la superficie de integraciones de LangChain (todo vector store, todo proveedor de modelos, todo document loader que se te ocurra) sigue siendo la vía más rápida para conectarlo. Si tu equipo ya tiene una versión de LangChain estable y pinneada en producción, con cobertura de tests alrededor, el costo de migración de una reescritura tiene que superar una vara real, no solo una tendencia. Un sistema que funciona, sin dolor al depurar, sin requisito multiagente y sin requisito de reanudabilidad, no es un sistema que necesite LangGraph. Publícalo, mantenlo, sigue adelante.
Cuándo migrar a LangGraph justifica la reescritura
La señal para migrar no es “LangGraph es más nuevo.” Es una lista concreta de síntomas, y vale la pena contrastar tu propia codebase con ella honestamente antes de empezar una reescritura:
- Estás depurando fallos opacos del agente más de una vez por semana, y cuando lo haces no consigues una traza de estado clara — estás leyendo logs para adivinar qué pasó en lugar de inspeccionar qué pasó.
- Necesitas que dos o más agentes se pasen trabajo, y ya estás escribiendo código de orquestación propio — un dict compartido, una cola de mensajes, un router hecho a mano — para lograrlo sobre un framework que asumió un solo agente todo el tiempo.
- Tus ejecuciones de agente son lo bastante largas o lo bastante importantes como para que una caída a mitad de tarea sin reanudabilidad sea un incidente real, y no una molestia que alguien vuelve a lanzar a mano.
- Tu flujo de control ha acumulado tantas ramas condicionales y bucles de reintento que estás peleando contra el modelo de bucle único de
AgentExecutoren vez de usarlo, y los workarounds empiezan a parecerse a una versión peor de un grafo de estado.
Si dos o más de esos son ciertos, la reescritura suele pagarse sola en un par de incidentes que de otro modo habrías pasado depurando a ciegas. Si ninguno lo es, no tienes un problema de framework — tienes un sistema que funciona, y la tendencia de búsqueda no es razón para tocarlo.
Cómo migrar de LangChain a LangGraph de forma incremental
El mapeo de conceptos de LangChain a LangGraph es más mecánico de lo que sugiere una reescritura completa. Una chain se convierte en una secuencia lineal de nodos. La memoria se convierte en el objeto de estado más un checkpointer. El bucle de herramientas de AgentExecutor se convierte en un nodo explícito que llama a las herramientas y una arista condicional que decide si volver a iterar o seguir. No tienes que migrar todo de una vez — aislar el bucle del agente en un subgrafo de LangGraph dejando en su sitio retrievers, loaders y otras integraciones de LangChain (LangGraph está hecho para interoperar con ellas, no para reemplazarlas por completo) es un camino incremental realista, y suele ser por donde empiezan los equipos.
Elige el checkpointer según cuánto viven realmente tus ejecuciones. Uno en memoria alcanza para tests, pero una ejecución que abarca minutos y sobrevive a un despliegue necesita un backend duradero, lo que en la práctica significa Postgres o Redis — la misma pregunta de durabilidad que te obliga a responder cualquier cola de trabajos en segundo plano, llegando con un disfraz nuevo.
Nada de esto va realmente sobre qué framework gana un concurso de popularidad. Es la misma pregunta de arquitectura que los ingenieros de backend se han hecho siempre sobre cualquier sistema: ¿la abstracción que usas encaja con la forma del problema que realmente tienes, o estás escribiendo código a su alrededor para compensar el desajuste? LangChain encajaba bien con la primera forma de las aplicaciones LLM. Los agentes en producción se salieron de esa forma. Toma la decisión sobre tu propia codebase con ese criterio, antes de que las sesiones de depuración y la gestión de estado atornillada la tomen por ti.
Relacionado: cuando tu grafo ya funciona, los nodos de enrutado son buenos candidatos para un pequeño modelo de decisión tipado. Mira Jev de TypeSafe.

