LangGraph vs CrewAI vs AutoGen: Guía Definitiva de Sistemas Multi-Agente en 2026
En 2025 construíamos un agente AI y ya. En 2026, la cosa cambió: ahora orquestamos varios agentes trabajando juntos.
El típico agente que intenta hacerlo todo suele colapsar. La nueva tendencia es dividir responsabilidades entre agentes especializados que colaboran como un equipo. Pero hay un problema: existen 3 frameworks principales—LangGraph, CrewAI y AutoGen—y cada uno tiene una filosofía completamente diferente. Elegir mal puede costarte semanas de refactorización.
En este artículo te voy a explicar las diferencias clave y cuándo usar cada uno. Con código real, por supuesto.
¿Por qué no basta con un solo agente?
Antes de meternos con los frameworks, veamos por qué los sistemas multi-agente se han vuelto esenciales.
Los límites del agente todopoderoso
Imagina que creas un bot de atención al cliente. Este agente tiene que:
- Identificar qué quiere el usuario
- Buscar información relevante en la base de datos
- Consultar datos de la cuenta del cliente
- Generar una respuesta apropiada
- Escalar a un humano si es necesario
Si un solo agente hace todo esto:
# El antipatrón del "Agente Dios" class CustomerServiceAgent: def handle_request(self, message: str) -> str: intent = self.classify_intent(message) context = self.search_knowledge_base(intent) account_info = self.get_account_info() response = self.generate_response(context, account_info) if self.should_escalate(response): return self.escalate_to_human() return response
¿Cuál es el problema?
- Te quedas sin tokens rápido: metes todo en el prompt y adiós context window
- El LLM se confunde: saltando de clasificar a generar respuestas
- Es lento: cosas que podrían correr en paralelo van en serie
- Debug imposible: cuando algo falla, tienes que revisar un prompt de 2000 líneas
La solución multi-agente
Dividiendo por roles queda así:
┌─────────────────────────────────────────────────────────────┐
│ ORCHESTRATOR │
│ (Dirige las peticiones al agente correcto) │
└─────────────────┬──────────────────────────────┬───────────┘
│ │
┌─────────────▼─────────────┐ ┌─────────────▼─────────────┐
│ CLASIFICADOR │ │ BUSCADOR │
│ (Detecta intención) │ │ (RAG specialist) │
└─────────────┬─────────────┘ └─────────────┬─────────────┘
│ │
┌─────────────▼─────────────┐ ┌─────────────▼─────────────┐
│ CUENTA │ │ REDACTOR │
│ (Consulta CRM) │ │ (Genera respuestas) │
└───────────────────────────┘ └───────────────────────────┘
Ventajas:
- Cada agente tiene un prompt corto y enfocado
- Los agentes independientes pueden correr en paralelo
- Si uno falla, el sistema no colapsa entero
- Puedes testear cada agente por separado
Ahora veamos cómo cada framework implementa esto.
LangGraph: Control total con grafos
LangGraph viene del equipo de LangChain. El concepto clave: modelar tu sistema de agentes como un grafo. Los nodos son funciones, las aristas son el flujo. Todo es explícito y visible.
La idea central
- Nodos = funciones (agentes, tools, lógica pura)
- Aristas = qué viene después
- Estado = los datos que pasan entre nodos
Mejor verlo en código:
from typing import Annotated, TypedDict from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langchain_openai import ChatOpenAI class AgentState(TypedDict): messages: Annotated[list, add_messages] current_intent: str knowledge_context: str account_info: dict should_escalate: bool def classify_intent(state: AgentState) -> AgentState: """Agente clasificador""" llm = ChatOpenAI(model="gpt-4o") response = llm.invoke([ {"role": "system", "content": "Clasifica la intención en: billing, technical, general, complaint"}, {"role": "user", "content": state["messages"][-1].content} ]) return {"current_intent": response.content.strip().lower()} def retrieve_knowledge(state: AgentState) -> AgentState: """Agente de búsqueda""" intent = state["current_intent"] knowledge_map = { "billing": "Política de facturación: reembolsos en 30 días...", "technical": "Troubleshooting: primero reinicia...", "general": "Sobre nosotros: somos una plataforma SaaS...", "complaint": "Gestión de quejas: lo tomamos muy en serio..." } return {"knowledge_context": knowledge_map.get(intent, "")} def lookup_account(state: AgentState) -> AgentState: """Agente de cuenta""" return { "account_info": { "tier": "premium", "tenure_months": 24, "open_tickets": 2 } } def generate_response(state: AgentState) -> AgentState: """Agente de respuesta""" llm = ChatOpenAI(model="gpt-4o") prompt = f"""Genera una respuesta útil basándote en: Intención: {state['current_intent']} Contexto: {state['knowledge_context']} Cuenta: {state['account_info']} Mensaje: {state['messages'][-1].content}""" response = llm.invoke([{"role": "user", "content": prompt}]) return {"messages": [response]} def check_escalation(state: AgentState) -> AgentState: should_escalate = ( state["current_intent"] == "complaint" and state["account_info"].get("tier") == "premium" ) return {"should_escalate": should_escalate} def route_after_check(state: AgentState) -> str: return "escalate" if state["should_escalate"] else "respond" def escalate_to_human(state: AgentState) -> AgentState: return { "messages": [ {"role": "assistant", "content": "Te conecto con un especialista."} ] } def build_graph(): workflow = StateGraph(AgentState) workflow.add_node("classify", classify_intent) workflow.add_node("retrieve", retrieve_knowledge) workflow.add_node("lookup", lookup_account) workflow.add_node("check_escalation", check_escalation) workflow.add_node("respond", generate_response) workflow.add_node("escalate", escalate_to_human) workflow.add_edge(START, "classify") workflow.add_edge("classify", "retrieve") workflow.add_edge("retrieve", "lookup") workflow.add_edge("lookup", "check_escalation") workflow.add_conditional_edges( "check_escalation", route_after_check, {"respond": "respond", "escalate": "escalate"} ) workflow.add_edge("respond", END) workflow.add_edge("escalate", END) return workflow.compile() graph = build_graph() result = graph.invoke({ "messages": [{"role": "user", "content": "Mi factura está mal!"}], "current_intent": "", "knowledge_context": "", "account_info": {}, "should_escalate": False })
Lo mejor de LangGraph
1. Visualización del flujo
from IPython.display import Image, display display(Image(graph.get_graph().draw_mermaid_png()))
2. Pausar y continuar
from langgraph.checkpoint.memory import MemorySaver memory = MemorySaver() graph = build_graph().compile(checkpointer=memory) config = {"configurable": {"thread_id": "user-123"}} result = graph.invoke({"messages": [...]}, config)
3. Aprobación humana fácil
from langgraph.types import interrupt def human_approval_node(state: AgentState) -> AgentState: if state["requires_approval"]: approval = interrupt("Reembolso > 500€, esperando aprobación del manager") return {"approved": approval} return state
¿Cuándo usar LangGraph?
✅ Sí:
- Necesitas control fino del flujo
- Auditoría y compliance son importantes
- Tienes lógica de branching compleja
- Ya usas LangChain
❌ No:
- Quieres prototipar rápido
- El flujo es simple
CrewAI: Equipos con roles
CrewAI tiene otro enfoque. Nada de grafos. Aquí defines roles y tareas como si montaras un equipo real.
La idea central
- Agent = miembro del equipo (rol, objetivo, personalidad)
- Task = lo que tiene que hacer
- Crew = el equipo completo
from crewai import Agent, Task, Crew, Process from crewai_tools import SerperDevTool classifier_agent = Agent( role="Analista de Intención", goal="Identificar qué quiere el cliente y clasificarlo", backstory="""Experto en entender a los clientes. Años de experiencia detectando si es un problema de facturación, técnico o una queja.""", verbose=True, allow_delegation=False ) researcher_agent = Agent( role="Investigador", goal="Encontrar la información necesaria para resolver el caso", backstory="""Conoce todas las políticas de la empresa. Siempre encuentra la info correcta.""", tools=[SerperDevTool()], verbose=True ) response_agent = Agent( role="Especialista en Respuestas", goal="Crear respuestas que dejen al cliente satisfecho", backstory="""Maestro de la comunicación. Convierte clientes enfadados en fans.""", verbose=True ) classification_task = Task( description="""Analiza el mensaje: Mensaje: {customer_message} Clasifica como billing, technical, general o complaint. Indica urgencia: low, medium, high.""", expected_output="Clasificación y urgencia", agent=classifier_agent ) research_task = Task( description="""Basándote en: {classification} Busca políticas y soluciones relevantes.""", expected_output="Info de políticas y solución propuesta", agent=researcher_agent, context=[classification_task] ) response_task = Task( description="""Con la investigación, redacta una respuesta: Mensaje original: {customer_message} Clasificación: {classification} Investigación: {research}""", expected_output="Respuesta para enviar al cliente", agent=response_agent, context=[classification_task, research_task] ) crew = Crew( agents=[classifier_agent, researcher_agent, response_agent], tasks=[classification_task, research_task, response_task], process=Process.sequential, verbose=True ) result = crew.kickoff(inputs={"customer_message": "Mi factura está mal!"})
Lo mejor de CrewAI
1. Modo jerárquico con manager
crew = Crew( agents=[...], tasks=[...], process=Process.hierarchical, manager_llm=ChatOpenAI(model="gpt-4o"), )
2. Memoria integrada
crew = Crew( agents=[...], tasks=[...], memory=True, )
¿Cuándo usar CrewAI?
✅ Sí:
- Quieres prototipar rápido
- Piensas en términos de roles
- Non-devs necesitan entender el sistema
❌ No:
- Necesitas control granular
- Resultados 100% deterministas
AutoGen: Agentes que chatean
AutoGen de Microsoft es diferente. Los agentes conversan para resolver problemas. Como un grupo de Slack discutiendo.
La idea central
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager import os config_list = [{"model": "gpt-4o", "api_key": os.environ["OPENAI_API_KEY"]}] llm_config = {"config_list": config_list} classifier = AssistantAgent( name="Classifier", system_message="""Eres el clasificador. Analiza mensajes e indica intención y urgencia.""", llm_config=llm_config ) researcher = AssistantAgent( name="Researcher", system_message="""Eres el investigador. Busca info relevante cuando te pasen una intención.""", llm_config=llm_config ) responder = AssistantAgent( name="Responder", system_message="""Eres el redactor de respuestas. Escribe respuestas amables. Termina con 'TERMINATE'.""", llm_config=llm_config ) human_proxy = UserProxyAgent( name="Customer", human_input_mode="NEVER", max_consecutive_auto_reply=0, code_execution_config=False ) group_chat = GroupChat( agents=[human_proxy, classifier, researcher, responder], messages=[], max_round=10, speaker_selection_method="round_robin" ) manager = GroupChatManager(groupchat=group_chat, llm_config=llm_config) human_proxy.initiate_chat(manager, message="Mi factura está mal!")
Lo mejor de AutoGen
1. Ejecuta código
coder = AssistantAgent( name="Coder", system_message="Eres experto en Python. Resuelve con código.", llm_config=llm_config ) executor = UserProxyAgent( name="Executor", code_execution_config={"work_dir": "workspace", "use_docker": True} ) executor.initiate_chat(coder, message="Crea una función de interés compuesto")
¿Cuándo usar AutoGen?
✅ Sí:
- Necesitas ejecutar código
- El problema requiere iteración
- Quieres que debatan soluciones
❌ No:
- Flujos predecibles
- Te preocupa el costo de tokens
Comparativa rápida
| Aspecto | LangGraph | CrewAI | AutoGen |
|---|---|---|---|
| En una frase | Grafos | Equipos | Chats |
| Curva | Media-alta | Baja | Media |
| Tokens | Eficiente | Normal | Alto |
| Debug | Visual | Logs | Difícil |
| Producción | Listo | Creciendo | Investigación |
Recomendaciones
| Caso de uso | Framework |
|---|---|
| Atención al cliente | LangGraph |
| Creación de contenido | CrewAI |
| Generación de código | AutoGen |
| MVP rápido | CrewAI |
Errores comunes
1. Demasiados agentes
Empieza con 2-3. Añade más solo cuando sea necesario.
2. Loops infinitos
Siempre pon límites:
graph.invoke(state, config={"recursion_limit": 25}) group_chat = GroupChat(max_round=10, ...)
3. Contexto que explota
Resume el contexto entre agentes:
def summarize(state): llm = ChatOpenAI(model="gpt-4o-mini") return llm.invoke([{"role": "user", "content": f"Resume en 100 palabras: {state}"}])
Conclusión
LangGraph → Control y producción
CrewAI → Rapidez y claridad
AutoGen → Código y debate
Los principios son los mismos:
- Empieza simple (2-3 agentes)
- Roles claros
- Manejo de errores
- Monitorización
Los frameworks están maduros. Es hora de construir.