Sistemas multi-agente: LangGraph vs CrewAI vs Autogen en 2026
Índice de contenidos
- Puntos clave
- Qué problema resuelve un sistema multi-agente
- LangGraph: grafo explícito, control fino
- CrewAI: equipos con roles, productividad rápida
- Autogen: conversación entre agentes, flexibilidad
- Caso real: pipeline de investigación + redacción + validación
- Tabla resumen: cuándo cada uno
- Conclusión
Comparar LangGraph, CrewAI y Autogen se reduce a elegir entre tres modelos mentales bien distintos: grafo explícito, jerarquía de roles y conversación de grupo. Este post desmonta cada paradigma con código canónico y resuelve el mismo pipeline real (investigar → redactar → validar) tres veces, una con cada framework, para que el patrón que mejor encaje con tu equipo aparezca solo. Ver también: la guía completa del mcp model context protocol, que enmarca el contexto en el que cualquier sistema multi-agente intercambia herramientas.
Puntos clave
- Gartner reporta una subida del 1.445% en consultas sobre sistemas multi-agente entre el primer trimestre de 2024 y el segundo de 2025, según su informe de tendencias 2026[1]; la categoría ha pasado de curiosidad a presupuesto en dieciocho meses.
- LangGraph modela la orquestación como una máquina de estados explícita: nodos puros, aristas tipadas, estado compartido con
TypedDicty reducers opcionales. - CrewAI modela la orquestación como una jerarquía de agentes con rol: cada agente tiene
role,goalybackstory; las tareas se encadenan porcontexty laCrewejecuta el proceso. - Autogen, en su rewrite v0.4, modela la orquestación como un grupo de chat:
AssistantAgents enRoundRobinGroupChatoSelectorGroupChatque se turnan según un selector configurable. - Los tres son válidos en producción; la decisión depende del coste de control fino, de la legibilidad para stakeholders no técnicos y del nivel de auditoría que exija el caso.
- La capa de observabilidad es ortogonal al framework: las convenciones GenAI de OpenTelemetry funcionan igual con los tres, como detalla la observabilidad de agentes con OTel GenAI.
Qué problema resuelve un sistema multi-agente
Un agente solo con tool use resuelve más de lo que parece. La pregunta es cuándo deja de bastar. Hay tres síntomas claros que empujan hacia multi-agente: el prompt único excede los límites razonables (system + ejemplos few-shot + RAG estático ya raspan los 10k tokens y pierdes coherencia), las responsabilidades pesan distinto (investigar, redactar y validar son trabajos con criterios opuestos), o necesitas paralelismo real (tres búsquedas independientes que luego se funden). En cualquiera de los tres, separar el problema en agentes especializados con un orquestador encima paga el sobrecoste de coordinación.
El mercado lo nota. Gartner registra un crecimiento del 1.445% en consultas sobre sistemas multi-agente entre Q1 2024 y Q2 2025 — una de las mayores aceleraciones que la firma ha medido en una categoría tecnológica reciente, según el informe de tendencias 2026[1]. Lo interesante para quien construye no es la cifra en sí, sino la consecuencia: hay tres modelos mentales que dominan la conversación —grafo, jerarquía y chat— y cada uno tiene un framework de referencia maduro detrás.
A partir de aquí los tres modelos se ven mejor en código. Lo que sigue son tres ejemplos canónicos —ninguna llamada a LLM real, sólo la glue de orquestación— y al final, el mismo pipeline resuelto tres veces.
LangGraph: grafo explícito, control fino
LangGraph trata la orquestación como un grafo dirigido: defines un estado tipado, registras nodos que mutan ese estado y declaras las transiciones con aristas. Los nodos especiales START y END marcan la entrada y la salida, las aristas condicionales se añaden con add_conditional_edges, y un compilador final devuelve un objeto invocable. La documentación de LangGraph[2] formaliza el patrón: StateGraph(State) para construir, compile() para sellar, invoke(initial_state) para ejecutar.
# langgraph_minimal.py
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
def add_messages(left: list, right: list) -> list:
return left + right
class State(TypedDict):
messages: Annotated[list, add_messages]
context: str
def analyze(state: State) -> dict:
return {"context": "analizado"}
def chatbot(state: State) -> dict:
return {"messages": [f"Respuesta a: {state['messages'][-1]}"]}
graph = StateGraph(State)
graph.add_node("analyze", analyze)
graph.add_node("chatbot", chatbot)
graph.add_edge(START, "analyze")
graph.add_edge("analyze", "chatbot")
graph.add_edge("chatbot", END)
app = graph.compile()
print(app.invoke({"messages": ["Hola"], "context": ""}))La gracia operativa es el control. Como las transiciones son explícitas, depurar un flujo que se desvía consiste en mirar dónde se rompe la condición de una arista; no hay magia detrás de un selector implícito. La penalización es la curva: hay que pensar como un ingeniero de sistemas distribuidos, diseñar el shape del estado y entender los reducers (Annotated[list, add_messages] no aparece en cualquier carrera). Para flujos deterministas con ramas condicionales, paralelismo y persistencia con checkpointer Postgres o Redis, el coste se amortiza pronto.
Tres patrones tiran de LangGraph en producción. El primero es la persistencia por hilo: con un InMemorySaver o un checkpointer Postgres, cada invoke enlaza con su hilo de conversación previo y soporta reanudación tras caída del proceso. El segundo es el grafo cíclico: add_conditional_edges("validador", router, {"ok": END, "reintentar": "redactor"}) cierra un bucle de validación con criterio explícito y, sobre todo, auditable en logs. El tercero es la composición: un sub-grafo entero se puede encapsular como nodo de un grafo padre, lo que ayuda a separar responsabilidades sin mezclar el shape del estado.
CrewAI: equipos con roles, productividad rápida
CrewAI parte de una intuición distinta: si un humano describiría el trabajo como “un investigador busca, una redactora escribe y un validador revisa”, deja que el código se lea igual. Los tres primitivos son Agent, Task y Crew, y la metáfora organizativa hace que un product manager pueda revisar un crew sin pedir traducción. Los detalles de cada parámetro están en la documentación de CrewAI[3]. Para profundizar en la pieza CrewAI específicamente, está la introducción dedicada en crewai equipos de agentes, que entra en detalles de herramientas y procesos jerárquicos.
# crewai_minimal.py
from crewai import Agent, Task, Crew, Process
investigador = Agent(
role="Investigador",
goal="Localizar fuentes técnicas relevantes sobre el tema dado",
backstory="Documentalista con quince años en publicaciones técnicas.",
)
redactor = Agent(
role="Redactor",
goal="Convertir la investigación en prosa clara para audiencia técnica",
backstory="Redactor que ha escrito para revistas de ingeniería.",
)
investigar = Task(
description="Investiga el tema X y devuelve cinco fuentes con cita.",
expected_output="Lista de cinco fuentes con URL y resumen de una frase.",
agent=investigador,
)
redactar = Task(
description="Redacta un artículo de 800 palabras a partir de la investigación.",
expected_output="Artículo en Markdown con introducción, tres secciones y cierre.",
agent=redactor,
context=[investigar],
)
crew = Crew(
agents=[investigador, redactor],
tasks=[investigar, redactar],
process=Process.sequential,
)
print(crew.kickoff(inputs={"tema": "vector databases en 2026"}))El sweet spot de CrewAI son los prototipos rápidos y las demos donde la legibilidad importa más que el control milimétrico. El proceso Process.sequential resuelve cadenas lineales en una llamada; Process.hierarchical añade un manager LLM que delega y reescribe planes. El coste oculto es la depuración: cuando un crew da vueltas o se queda corto, la lógica de control vive dentro de prompts y no de aristas, y rastrear el porqué es más laborioso que en un grafo explícito. Ver también: la guía sobre vector databases con pgvector en producción si vas a conectar el crew a una base de RAG real.
Hay dos detalles concretos que conviene fijar desde el primer prototipo. Primero, el expected_output no es decoración: el modelo lo lee y lo usa como contrato; si lo dejas vago (“un buen artículo”) la validación posterior te encuentra desviaciones difíciles de explicar. Segundo, las dependencias entre tareas se declaran con context=[task_anterior] y eso es lo que pasa el resultado al siguiente prompt; no hay variables globales ni paso implícito de datos. Y un tercer apunte para equipos que ya operan en castellano peninsular: los role, goal y backstory se pueden escribir en español sin penalización si el modelo elegido es multilingüe — el framework no impone idioma.
Autogen: conversación entre agentes, flexibilidad
Autogen partió en 2023 con el patrón “conversación entre agentes” y, tras la reescritura v0.4 publicada en 2024–2025, su forma canónica para 2026 vive en el paquete autogen_agentchat. Cada agente es un AssistantAgent con su system_message, el modelo cliente se inyecta desde autogen_ext, y los agentes se agrupan en un team —RoundRobinGroupChat, SelectorGroupChat— que decide quién habla en cada turno. La documentación oficial de Autogen[4] detalla los selectores disponibles y el patrón asíncrono.
# autogen_minimal.py
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import MaxMessageTermination
from autogen_ext.models.openai import OpenAIChatCompletionClient
model_client = OpenAIChatCompletionClient(model="gpt-4o")
planner = AssistantAgent(
name="planner",
model_client=model_client,
system_message="Propones planes en pasos numerados.",
)
critic = AssistantAgent(
name="critic",
model_client=model_client,
system_message="Criticas el plan y propones mejoras concretas.",
)
team = RoundRobinGroupChat(
[planner, critic],
termination_condition=MaxMessageTermination(max_messages=4),
)
async def main() -> None:
async for msg in team.run_stream(task="Plan para migrar a OTel GenAI."):
print(msg)
asyncio.run(main())Autogen brilla en tareas de razonamiento abierto donde no se sabe a priori qué experto necesita actuar, en debates entre roles complementarios (writer + critic), y donde un humano puede entrar como agente más sin ceremonia. Su precio es la trazabilidad: el flujo emerge de la conversación, así que la auditoría depende de la instrumentación que tú añadas. Aquí encajan las convenciones GenAI de OpenTelemetry como capa transversal independiente del framework.
La elección entre RoundRobinGroupChat y SelectorGroupChat resume bien el espectro. El round-robin es predecible: el orden de los agentes en la lista es el orden de turnos. El selector es flexible: puedes pasar una función selector_func que decide en cada turno qué agente habla, o dejar que un LLM intermedio actúe de moderador. La regla práctica que ha funcionado en proyectos en 2025–2026 es empezar siempre por round-robin con MaxMessageTermination para acotar el coste, y migrar a selector cuando la heurística de quién habla esté clara. La trampa habitual es lanzar selectores LLM sin terminación bien definida y descubrir que el equipo se queda en bucle gastando tokens en silencio.
Caso real: pipeline de investigación + redacción + validación
El mismo pipeline resuelto tres veces. Tres etapas — investigate, draft, validate — encadenadas en orden, sin llamadas reales a LLM (las he sustituido por funciones que ilustran únicamente la glue de orquestación). El objetivo es ver, lado a lado, qué tiene que escribir un equipo en cada framework.
# === LangGraph ===
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
class S(TypedDict):
topic: str
research: str
draft: str
valid: bool
def investigate(s: S) -> dict:
return {"research": f"sources({s['topic']})"}
def draft(s: S) -> dict:
return {"draft": f"article from {s['research']}"}
def validate(s: S) -> dict:
return {"valid": "sources" in s["research"]}
g = StateGraph(S)
g.add_node("investigate", investigate)
g.add_node("draft", draft)
g.add_node("validate", validate)
g.add_edge(START, "investigate")
g.add_edge("investigate", "draft")
g.add_edge("draft", "validate")
g.add_edge("validate", END)
pipeline_lg = g.compile()# === CrewAI ===
from crewai import Agent, Task, Crew, Process
inv = Agent(role="Investigador", goal="Listar fuentes", backstory="Doc.")
red = Agent(role="Redactor", goal="Escribir artículo", backstory="Periodista.")
val = Agent(role="Validador", goal="Verificar fuentes", backstory="Editor.")
t1 = Task(description="Investiga {topic}", expected_output="Lista", agent=inv)
t2 = Task(description="Redacta artículo", expected_output="MD", agent=red, context=[t1])
t3 = Task(description="Valida fuentes", expected_output="OK/KO", agent=val, context=[t2])
pipeline_cw = Crew(agents=[inv, red, val], tasks=[t1, t2, t3], process=Process.sequential)# === Autogen v0.4 ===
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import MaxMessageTermination
from autogen_ext.models.openai import OpenAIChatCompletionClient
mc = OpenAIChatCompletionClient(model="gpt-4o")
investigator = AssistantAgent("investigator", model_client=mc, system_message="Investiga.")
drafter = AssistantAgent("drafter", model_client=mc, system_message="Redacta.")
validator = AssistantAgent("validator", model_client=mc, system_message="Valida.")
pipeline_ag = RoundRobinGroupChat(
[investigator, drafter, validator],
termination_condition=MaxMessageTermination(max_messages=6),
)
# asyncio.run(pipeline_ag.run(task="vector databases 2026"))Tres formas de decir lo mismo, tres compromisos distintos. LangGraph hace el orden explícito en aristas; CrewAI lo hace en context=[...] entre tareas; Autogen lo hace en el selector del team y se apoya en el modelo para que cada agente cumpla su papel. Cuanto más rígido el orden y más crítica la auditoría, más a la izquierda de esa lista te conviene caer. Para el cableado de observabilidad común a los tres, mira el tutorial del SDK de Anthropic y la sibling observabilidad GenAI con OTel, porque las trazas son ortogonales al framework.
Tabla resumen: cuándo cada uno
| Framework | Modelo mental | Sweet spot | Curva de aprendizaje | Observabilidad | Cuándo NO |
|---|---|---|---|---|---|
| LangGraph | Grafo / DAG explícito | Flujos deterministas con ramas y persistencia | Media-alta | Nativa con LangSmith + OTel GenAI | Prototipo rápido sin equipo de ingeniería |
| CrewAI | Equipo con roles | Demos, comunicación con stakeholders | Baja | Decente vía callbacks; OTel manual | Flujos con muchas ramas condicionales |
| Autogen | Conversación de grupo | Razonamiento abierto, critic loops | Media | Manual (OTel GenAI semconv) | Auditoría estricta o reproducibilidad bit-exact |
Las tres líneas no son verdades absolutas; son el primer corte. Un equipo que ya vive en LangChain probablemente prefiera LangGraph aunque su flujo sea simple; un equipo de producto que necesita iterar con marketing probablemente vaya a CrewAI aunque haya bordes raros; un equipo de research que mezcla agentes y humanos en bucle probablemente acabe en Autogen aunque la auditoría duela.
La pregunta que más rinde antes de elegir no es “qué framework es mejor” sino “qué propiedad necesito conservar pase lo que pase con el flujo”. Si la respuesta es reproducibilidad bit-exact con auditoría externa, LangGraph se cae solo del estante. Si es velocidad de iteración con stakeholders no técnicos, CrewAI gana por legibilidad. Si es exploración de espacios de razonamiento donde la conversación es el producto, Autogen es la opción natural. La capa de observabilidad —trazas OTel, métricas de coste por agente, dashboards de latencia por turno— se monta encima de los tres con el mismo set de atributos GenAI semconv y se reutiliza sin reescribir cuando cambias de framework, lo que rebaja una buena parte del riesgo de la decisión inicial.
Conclusión
Los tres frameworks resuelven el mismo problema con tres lenguajes distintos, y la decisión correcta depende de a quién va a leer el código y qué pruebas se le piden al sistema. LangGraph paga su curva con control fino y aristas auditables; CrewAI paga su simplicidad con depuración más opaca pero excelente legibilidad; Autogen paga su flexibilidad con trazabilidad que tú instrumentas. Si tienes que apostar por uno sin contexto adicional, empieza por CrewAI para validar el modelo mental con stakeholders, prototipa la lógica crítica en LangGraph cuando el flujo se estabilice, y reserva Autogen para los casos donde la conversación entre roles sea el producto mismo.
Síguenos en jacar.es para más sobre orquestación de agentes, MCP, observabilidad GenAI y patrones reales del ecosistema multi-agente en 2026.