DEV Community

Moon Robert
Moon Robert

Posted on • Originally published at blog.rebalai.com

AutoGen vs LangGraph vs CrewAI: Lo que aprendí después de dos semanas probándolos en producción

Hace dos meses, mi equipo (somos cuatro personas, dos backend, una de ML y yo) necesitaba automatizar algo concreto: un pipeline que tomara tickets de Jira, generara un primer borrador de código, lo revisara contra nuestros estándares internos y produjera documentación. Nada del otro mundo en teoría, pero bastante complicado en la práctica cuando empiezas a pensar en estados, errores, y el inevitables momento en que el LLM alucina algo completamente incorrecto en el paso 2 de 5.

Pasé literalmente dos semanas probando AutoGen, LangGraph y CrewAI para este caso. No tutoriales de YouTube. No demos de "hola mundo". El sistema real, con nuestras herramientas, nuestros datos y nuestra tolerancia cero a que el agente se quede en bucle infinito a las 3am.

Esto es lo que encontré.


AutoGen 0.5: Potente, pero te exige entender su modelo mental primero

AutoGen (de Microsoft) pasó por una reescritura bastante traumática entre la versión 0.2 y 0.4. La gente que conocía la API anterior tuvo que reaprender casi todo. Para marzo de 2026, la versión 0.5 ya está bastante estable y el concepto central es claro: todo gira alrededor de conversaciones entre agentes.

Tienes agentes que hablan entre sí. Uno hace una pregunta, otro responde, un tercero interviene si detecta que la conversación llegó a algún criterio. Es un modelo que a primera vista parece natural — oye, así trabajamos los humanos, ¿no? — pero en la práctica te complica la cabeza cuando necesitas control fino sobre el flujo.

Lo que me gustó: la abstracción de GroupChat es genuinamente útil cuando tienes procesos donde los agentes necesitan deliberar. Armé un prototipo en medio día donde un agente "analista" revisaba el ticket y un agente "codificador" proponía soluciones, con un tercer agente actuando como "crítico". El código base era sorprendentemente conciso:

import autogen

# Configuración básica — en producción esto viene de variables de entorno
llm_config = {
    "model": "claude-sonnet-4-6",
    "api_key": os.environ["ANTHROPIC_API_KEY"],
    "temperature": 0.2,
}

analista = autogen.AssistantAgent(
    name="Analista",
    system_message="Eres un analista técnico. Descompón el ticket en tareas concretas.",
    llm_config=llm_config,
)

codificador = autogen.AssistantAgent(
    name="Codificador",
    system_message="Escribe código Python limpio basado en las tareas del analista.",
    llm_config=llm_config,
)

critico = autogen.AssistantAgent(
    name="Critico",
    system_message=(
        "Revisa el código. Si cumple los estándares, responde APPROVED. "
        "Si no, explica qué falta."
    ),
    llm_config=llm_config,
)

user_proxy = autogen.UserProxyAgent(
    name="Orquestador",
    human_input_mode="NEVER",  # Sin intervención humana
    max_consecutive_auto_reply=10,
    is_termination_msg=lambda msg: "APPROVED" in msg.get("content", ""),
)

groupchat = autogen.GroupChat(
    agents=[user_proxy, analista, codificador, critico],
    messages=[],
    max_round=15,
)
manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)

user_proxy.initiate_chat(manager, message=ticket_description)
Enter fullscreen mode Exit fullscreen mode

Funciona. El problema que encontré: el max_round=15 es mi forma de evitar que se quede dando vueltas para siempre. AutoGen no tiene un mecanismo nativo particularmente elegante para manejar ciclos y condiciones de salida complejas. Cuando el crítico rechazaba el código tres veces seguidas y el codificador seguía produciendo la misma solución incorrecta, el sistema simplemente... seguía. Tuve que construir lógica externa para detectar eso.

La observabilidad también me decepcionó un poco. Sí, puedes loggear las conversaciones, pero integrar eso con tu sistema de trazabilidad existente requiere trabajo manual. Para un equipo pequeño como el mío, ese overhead importa.

Takeaway de AutoGen: Ideal si tu problema se modela naturalmente como una conversación entre roles. Si necesitas control de flujo fino o tu proceso tiene muchos branches condicionales, vas a luchar contra el framework.


LangGraph 0.3: El framework que te deja construir exactamente lo que necesitas (a cambio de más código)

LangGraph viene del equipo de LangChain y es, básicamente, una máquina de estados para agentes. Defines nodos, defines edges, y el estado fluye entre ellos. Es más verboso que AutoGen — eso no lo voy a negar — pero esa verbosidad es exactamente lo que buscaba para mi caso.

La metáfora mental que me funcionó: AutoGen es como diseñar una reunión con personas que interactúan libremente. LangGraph es como diseñar un proceso de manufactura donde cada estación tiene una función específica y el producto pasa de una a otra de forma determinista.

Para el pipeline de tickets, LangGraph me permitió hacer algo que AutoGen complicaba: tener una lógica explícita de reintento con backoff, detectar cuando un paso fallaba y redirigir a un nodo de "recuperación", y exponer el estado intermedio al sistema de monitoreo de nuestra infraestructura sin trucos.

from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator

class EstadoPipeline(TypedDict):
    ticket: str
    tareas: list[str]
    codigo: str
    revision: str
    intentos_revision: Annotated[int, operator.add]  # se acumula automáticamente
    aprobado: bool

def analizar_ticket(estado: EstadoPipeline) -> dict:
    # Llama al LLM, descompone el ticket
    tareas = llm_analizar(estado["ticket"])
    return {"tareas": tareas}

def generar_codigo(estado: EstadoPipeline) -> dict:
    codigo = llm_codificar(estado["tareas"])
    return {"codigo": codigo}

def revisar_codigo(estado: EstadoPipeline) -> dict:
    revision = llm_revisar(estado["codigo"])
    aprobado = "APPROVED" in revision
    return {
        "revision": revision,
        "aprobado": aprobado,
        "intentos_revision": 1,  # se suma al total gracias a Annotated
    }

def debe_reintentar(estado: EstadoPipeline) -> str:
    if estado["aprobado"]:
        return "fin"
    if estado["intentos_revision"] >= 3:
        return "escalar"  # nodo especial para casos sin solución
    return "regenerar"

graph = StateGraph(EstadoPipeline)
graph.add_node("analizar", analizar_ticket)
graph.add_node("codificar", generar_codigo)
graph.add_node("revisar", revisar_codigo)
graph.add_node("escalar", notificar_equipo_humano)

graph.set_entry_point("analizar")
graph.add_edge("analizar", "codificar")
graph.add_edge("codificar", "revisar")
graph.add_conditional_edges(
    "revisar",
    debe_reintentar,
    {"fin": END, "regenerar": "codificar", "escalar": "escalar"},
)

pipeline = graph.compile()
Enter fullscreen mode Exit fullscreen mode

Esto es más código. Pero mira lo que ganas: el nodo escalar es explícito. El límite de reintentos es parte del estado, no un hack. Y si mañana necesito agregar un paso de "validar sintaxis" entre codificar y revisar, sé exactamente dónde va.

Lo que me tomó tiempo entender (y esto es un gotcha real): el tipado con TypedDict y los Annotated para state reducers. La primera vez que intenté acumular un contador sin Annotated, LangGraph simplemente sobreescribía el valor en cada nodo en lugar de acumularlo. Estuve 40 minutos debugueando eso. La documentación lo explica, pero es fácil saltárselo cuando estás prototipando rápido.

La integración con LangSmith para trazabilidad es genuinamente buena — mejor que cualquier cosa que tuve que improvisar con AutoGen. Con un par de variables de entorno, cada ejecución del pipeline queda trazada con sus inputs, outputs y el path exacto que tomó por el grafo.

Takeaway de LangGraph: Si tu proceso tiene lógica condicional, reintentos, o necesitas observabilidad de producción sin armar todo desde cero, este es probablemente tu mejor opción. La curva de entrada es real, pero la inversión vale.


CrewAI 1.2: El más accesible, con límites que vas a tocar más rápido de lo que esperas

CrewAI es el framework que más le recomendaría a alguien que está empezando con agentes y quiere algo funcionando esta tarde. La abstracción de "Crew + Agents + Tasks" es intuitiva, la documentación está bien mantenida, y el tiempo de prototipo es el más corto de los tres.

Lo que me sorprendió fue lo bien que funciona para casos de uso lineales. Defines agentes con roles y herramientas, defines tareas con dependencias, y CrewAI se encarga de la orquestación. Para nuestro pipeline, el primer prototipo con CrewAI estuvo listo en menos de dos horas.

Pero — y aquí está el límite que mencioné — cuando quise implementar la lógica de reintento condicional que sí logré en LangGraph, me encontré peleando contra la abstracción. CrewAI asume un flujo más o menos lineal (o con parallelismo simple). Los flows más complejos requieren usar su API de Flow (introducida en 2024), que está bien pero añade complejidad y te acerca bastante a lo que ya ofrece LangGraph de forma más explícita.

No voy a pegar un snippet completo de CrewAI porque honestamente ya hay docenas en su documentación oficial y no añadiría nada. Lo que sí vale mencionar: el manejo de errores en la versión 1.2 mejoró bastante respecto a versiones anteriores. El verbose=True en producción genera demasiado ruido — aprende de mi error y configura un logger personalizado desde el principio.

Un detalle que no vi mencionado en casi ningún benchmark: CrewAI consume bastante más tokens por tarea que LangGraph para casos equivalentes, porque los prompts del sistema que genera internamente son más voluminosos. No es dramático, pero si estás pagando por token y tienes volumen alto, es algo a medir.

Takeaway de CrewAI: Para prototipos, para equipos que no tienen un ingeniero de ML dedicado, o para pipelines relativamente lineales, es excelente. Cuando necesitas control fino, estarás mejor empezando con LangGraph desde el inicio.


Lo que los benchmarks no te cuentan: el costo real es en debugging

Hay algo que ningún artículo de comparación menciona suficientemente: el tiempo que pasas debugueando no el código que escribiste, sino el comportamiento del LLM dentro de tu agente.

Con AutoGen, cuando algo falla, lees una transcripción de conversación. Eso puede ser útil o puede ser una pesadilla dependiendo de qué tan detallado necesites ser. Con LangGraph, el estado explícito hace que debugging sea mucho más parecido a debuggear código normal — puedes imprimir el estado en cualquier nodo y saber exactamente qué información tenía el agente en ese momento. Con CrewAI, si una tarea falla silenciosamente (que pasó un par de veces en mi prueba), a veces tienes que ir al verbose log completo para entender qué pasó.

No soy 100% seguro de que esto escale de la misma manera más allá de sistemas con 5-6 agentes — cuando el número de agentes crece, todas las herramientas empiezan a tener problemas de observabilidad que requieren trabajo adicional. Esa es mi intuición después de dos semanas, pero no lo llevé hasta ese límite.

Otro punto práctico: si tu equipo ya usa LangChain para otras cosas, LangGraph tiene fricción de adopción casi cero. Si no usan LangChain, ese factor se neutraliza completamente.


Mi recomendación concreta, sin "depende de tu caso de uso"

Sé que la respuesta cómoda es "depende", pero eso no ayuda a nadie que tiene que tomar una decisión esta semana.

Para equipos pequeños construyendo algo en producción con lógica condicional real: LangGraph. La inversión en la curva de aprendizaje se amortiza rápido cuando llega el primer bug en producción y puedes trazarlo en minutos en lugar de horas. El tipado explícito del estado me salvó de por lo menos tres bugs que en AutoGen o CrewAI habrían sido mucho más difíciles de rastrear.

Para prototipos y validación de ideas: CrewAI. Es genuinamente el más rápido para llegar a algo demo-able. Si después necesitas más control, la reescritura en LangGraph no es dramática porque los conceptos son trasladables.

Para sistemas donde la deliberación entre agentes es el núcleo del producto — no solo un mecanismo de orquestación — AutoGen tiene su lugar. Si estás construyendo algo donde los agentes realmente necesitan negociar, argumentar, y llegar a consenso, el modelo de conversación de AutoGen es más natural que simular eso con un grafo de estados.

Nosotros terminamos con LangGraph en producción. Llevamos seis semanas corriendo el pipeline sin incidentes graves, con trazabilidad decente y — lo más importante — con la confianza de que cuando algo falle, vamos a poder entender por qué.

Top comments (0)