Frameworks para agentes de IA: LangGraph vs CrewAI vs OpenAI
Comparamos el mismo agente en 5 versiones: sin framework, OpenAI Agents SDK, LangGraph, CrewAI y Claude Agent SDK. Coste, dependencias y líneas de código.
👁 114 lecturas
He programado el mismo agente de IA cinco veces: sin framework, con OpenAI Agents SDK, LangGraph, CrewAI y Claude Agent SDK. Cada versión recibió las mismas tres herramientas y exactamente la misma tarea; a partir de ahí, medí las líneas de código, el tiempo, el número de peticiones al modelo y el coste. La respuesta rápida: para aprender y construir agentes sencillos, lo mejor es tu propio bucle o OpenAI Agents SDK; LangGraph se impone en flujos complejos; CrewAI destaca en equipos de agentes con roles definidos; y Claude Agent SDK brilla cuando el agente debe operar sobre archivos al estilo de Claude Code. Este artículo forma parte de la guía Agentes de IA desde cero.
Estado a 4 de octubre de 2026
- Versiones utilizadas:
openai3.24.0,openai-agents0.23.1,langgraph1.2.12 conlangchain-openai1.6.7,crewai1.15.23 yclaude-agent-sdk0.2.163 (con Claude Code 2.1.287). - Modelo en las cuatro primeras versiones:
openai/gpt-5.6-luna. Claude Agent SDK solo opera con modelos de Anthropic, por lo que alli se empleo Claude Haiku 4.5. Todas las conexiones se gestionaron mediante OpenRouter. - Cada versión se ejecutó 3 veces. Las consultas y el coste se registraron con un contador local por el que pasó todo el tráfico hacia OpenRouter.
- Las 15 ejecuciones de medicion arrojaron el resultado correcto (sin contar dos intentos iniciales con Claude Agent SDK que fallaron por configuracion y que explico mas abajo). Coste total de la prueba: unos 0,054 EUR (0,060 USD; tipo de cambio de referencia del BCE del 12/10/2026: 1 EUR = 1,1181 USD, ver https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml).
La tarea de prueba
El agente debe calcular el gasto total a partir de unos archivos de facturas en una carpeta local dane/ (en el experimento original se procesaron dos facturas en moneda local y una de 120 EUR, convirtiendo divisas mediante un endpoint bancario oficial). Las herramientas son identicas para todas las versiones y residen en un modulo aparte:
szukaj_plikow: examina y devuelve el contenido de los archivos .txt de la carpeta;kalkulator: evaluacion aritmetica segura;czytaj_strone: descarga paginas web o respuestas JSON de una API.
"""Herramientas comunes para todas las versiones del agente (funciones estandar de Python, sin framework)."""
import ast, operator, pathlib
import requests
from bs4 import BeautifulSoup
KATALOG = (pathlib.Path(__file__).parent.parent / "dane").resolve()
# Nota: La instruccion y la tarea se probaron en polaco en el test original.
# Se traducen aqui los textos como referencia:
ZADANIE = ("Calcula cuanto gaste en total en las facturas de la carpeta dane. "
"Convierte la factura en euros segun el tipo de cambio actual de la API oficial.")
INSTRUKCJA = ("Resuelve la tarea usando las herramientas. Endpoint de divisas: https://api.nbp.pl/api/exchangerates/rates/a/{kod}/?format=json. "
"Haz los calculos siempre con la calculadora. Responde de forma breve.")
def szukaj_plikow(fraza: str = "") -> str:
"""Muestra los archivos .txt de la carpeta dane/ y su contenido. Cadena vacia = todos los archivos."""
out = [f"== {p.relative_to(KATALOG)} ==\n{p.read_text(encoding='utf-8')[:1500]}"
for p in sorted(KATALOG.rglob("*.txt")) if fraza.lower() in p.read_text(encoding="utf-8").lower()]
return "\n".join(out) or "sin archivos"
OPS = {ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.USub: operator.neg}
def kalkulator(wyrazenie: str) -> str:
"""Calcula una expresion aritmetica, por ejemplo: 2214+1180.8."""
def licz(n):
if isinstance(n, ast.Constant): return n.value
if isinstance(n, ast.BinOp): return OPS[type(n.op)](licz(n.left), licz(n.right))
if isinstance(n, ast.UnaryOp): return OPS[type(n.op)](licz(n.operand))
raise ValueError("solo numeros y + - * /")
return str(round(licz(ast.parse(wyrazenie, mode="eval").body), 4))
def czytaj_strone(url: str) -> str:
"""Obtiene el texto de una pagina web o la respuesta de una API desde una URL."""
r = requests.get(url, timeout=20, headers={"User-Agent": "agentes-starter/1.0"})
return BeautifulSoup(r.text, "html.parser").get_text(" ", strip=True)[:4000]
De esta manera, la comparativa analiza unicamente la sobrecarga estructural del framework y no la implementacion de las herramientas. Si quieres ver como funciona el bucle de un agente por dentro, lo explico paso a paso en Como crear un agente de IA en Python.
Resultados de la comparativa
Precios en EUR calculados al cambio oficial del BCE de 1 EUR = 1,1181 USD (12/10/2026, fuente: ecb.europa.eu):
| Versión | Líneas de código | Tiempo medio | Peticiones al modelo | Coste medio por tarea | Paquetes a instalar | Tiempo de importacion | Exito |
|---|---|---|---|---|---|---|---|
| Sin framework (openai) | 16 | 7,3 s | 3 | aprox. 0,00057 EUR (0,00064 USD) | 14 | 0,6 s | 3/3 |
| OpenAI Agents SDK | 10 | 8,8 s | 3-4 | aprox. 0,00074 EUR (0,00083 USD) | 39 | 1,3 s | 3/3 |
| LangGraph | 19 | 7,9 s | 3 | aprox. 0,00055 EUR (0,00062 USD) | 43 | 1,3 s | 3/3 |
| CrewAI | 10 | 10,5 s | 3-4 | aprox. 0,00065 EUR (0,00073 USD) | 137 | 1,9-2,5 s | 3/3 |
| Claude Agent SDK (Haiku 4.5) | 24 | 16,1 s | 4-5 | aprox. 0,0133 EUR (0,0149 USD) | 31 + Claude Code | 0,7-1,0 s | 3/3 |
| Sin framework, mismo Haiku 4.5 (control) | 16 | 7,1 s | 4 | aprox. 0,0063 EUR (0,0071 USD) | 14 | 0,6 s | 1/1 |
Criterios de medicion:
- Líneas de código: lineas no vacias y sin comentarios, excluyendo el archivo comun de herramientas;
- Tiempo: desde el inicio del proceso de Python hasta el resultado final (incluyendo importaciones de librerias). Media de 3 ejecuciones;
- Paquetes: total de dependencias resueltas por pip junto con el framework (entorno Python 3.13);
- Coste: suma del campo
costdevuelto por OpenRouter tras cada llamada.
Conclusiones directas:
- En un agente sencillo, el framework apenas influye en el coste. Las versiones ejecutadas con GPT-5.6 Luna oscilan entre 0,0006 y 0,0009 USD (unos 0,0005 - 0,0008 EUR). OpenAI Agents SDK y CrewAI realizaron a veces una cuarta llamada (pasos de calculo separados en vez de uno conjunto), elevando minimamente la media.
- Claude Agent SDK resulta notablemente mas caro y lento, pero principalmente a causa del modelo. El test de control aclara el reparto: Haiku en un bucle propio costo 0,0071 USD (aprox. 0,0063 EUR), mientras que en Claude Agent SDK alcanzo 0,0149 USD (aprox. 0,0133 EUR). Cerca de la mitad de ese incremento se debe al propio motor de Claude Code (instrucciones de sistema mas extensas y fases de razonamiento antes de cada accion).
- CrewAI arrastra el mayor volumen de dependencias (137 paquetes, unos 790 MB en disco) y tiene la importacion mas pesada. Recomiendo instalarlo en un entorno virtual aislado para evitar colisiones de versiones.
1. Sin framework: 16 lineas
import json, os
from openai import OpenAI
from narzedzia import ZADANIE, INSTRUKCJA, szukaj_plikow, kalkulator, czytaj_strone
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"])
FUNKCJE = {f.__name__: f for f in (szukaj_plikow, kalkulator, czytaj_strone)}
TOOLS = [{"type": "function", "function": {"name": n, "description": f.__doc__, "parameters": {"type": "object",
"properties": {p: {"type": "string"} for p in f.__annotations__ if p != "return"}}}} for n, f in FUNKCJE.items()]
messages = [{"role": "system", "content": INSTRUKCJA}, {"role": "user", "content": ZADANIE}]
for krok in range(8):
msg = client.chat.completions.create(model=os.environ["MODEL"], messages=messages, tools=TOOLS).choices[0].message
messages.append(msg.model_dump(exclude_none=True))
if not msg.tool_calls:
print(msg.content); break
for c in msg.tool_calls:
wynik = FUNKCJE[c.function.name](**json.loads(c.function.arguments or "{}"))
messages.append({"role": "tool", "tool_call_id": c.id, "content": wynik})
Todo queda a la vista: la lista de mensajes, el bucle principal y la ejecucion de llamadas a funciones. La descripcion de las herramientas se genera directamente desde los docstrings. Prescinde de registros avanzados, reintentos ante caidas de red o gestion de argumentos invalidos; en un proyecto real anadirias todo eso en unas 30-50 lineas adicionales, tal como detallo en la versión completa del agente.
2. OpenAI Agents SDK: 10 lineas
import os
from openai import AsyncOpenAI
from agents import Agent, OpenAIChatCompletionsModel, Runner, function_tool, set_tracing_disabled
from narzedzia import ZADANIE, INSTRUKCJA, szukaj_plikow, kalkulator, czytaj_strone
set_tracing_disabled(True)
model = OpenAIChatCompletionsModel(model=os.environ["MODEL"], openai_client=AsyncOpenAI(
base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"]))
agent = Agent(name="Facturas", instructions=INSTRUKCJA, model=model,
tools=[function_tool(f) for f in (szukaj_plikow, kalkulator, czytaj_strone)])
print(Runner.run_sync(agent, ZADANIE, max_turns=8).final_output)
La formulacion mas concisa y funcional. function_tool infiere el esquema a partir de la firma de la funcion y Runner.run_sync gestiona el bucle con un limite max_turns. A cambio, obtienes de serie handoffs (traspaso de conversacion entre agentes), guardrails, sesiones y trazabilidad. En OpenRouter es necesario desactivar el tracing y envolver el cliente con OpenAIChatCompletionsModel, ya que por defecto el SDK se comunica con la API Responses de OpenAI.
3. LangGraph: 19 lineas
import os
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState, START
from langgraph.prebuilt import ToolNode, tools_condition
from narzedzia import ZADANIE, INSTRUKCJA, szukaj_plikow, kalkulator, czytaj_strone
narzedzia = [szukaj_plikow, kalkulator, czytaj_strone]
llm = ChatOpenAI(model=os.environ["MODEL"], base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"]).bind_tools(narzedzia)
def model(stan: MessagesState):
return {"messages": [llm.invoke(stan["messages"])]}
graf = StateGraph(MessagesState)
graf.add_node("model", model)
graf.add_node("tools", ToolNode(narzedzia))
graf.add_edge(START, "model")
graf.add_conditional_edges("model", tools_condition) # ¿hay llamadas a herramientas? -> "tools", si no -> fin
graf.add_edge("tools", "model")
agent = graf.compile()
wynik = agent.invoke({"messages": [("system", INSTRUKCJA), ("user", ZADANIE)]}, {"recursion_limit": 16})
print(wynik["messages"][-1].content)
Requiere mas lineas, pero he construido el grafo de forma explicita en lugar de recurrir a constructores predefinidos de una sola funcion. Refleja fielmente la filosofia de LangGraph: estado (historial de mensajes), nodos (modelo, herramientas) y aristas (condiciones como «determinar si el modelo solicita una herramienta»). Para un único agente puede parecer redundante; no obstante, en flujos con ramificaciones, aprobación humana intermedia, persistencia de estado y reanudación tras fallos, este diseño ahorra días de trabajo. El límite de ejecución se controla con recursion_limit.
4. CrewAI: 10 lineas
import os
from crewai import Agent, Task, Crew, LLM
from crewai.tools import tool
from narzedzia import ZADANIE, INSTRUKCJA, szukaj_plikow, kalkulator, czytaj_strone
llm = LLM(model="openrouter/" + os.environ["MODEL"], base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"])
ksiegowy = Agent(role="Contable", goal="Calcular los gastos de las facturas", backstory=INSTRUKCJA, llm=llm,
tools=[tool(f) for f in (szukaj_plikow, kalkulator, czytaj_strone)], max_iter=8, verbose=False)
zadanie = Task(description=ZADANIE, expected_output="Suma total con un breve desglose", agent=ksiegowy)
print(Crew(agents=[ksiegowy], tasks=[zadanie]).kickoff().raw)
CrewAI articula el problema en torno a personajes: cada agente cuenta con un rol, un objetivo y un trasfondo (backstory), mientras que la tarea define su descripcion y el formato esperado. Para un caso unitario implica bastante ceremonia, pero si necesitas coordinar varios perfiles (por ejemplo, un investigador que extrae datos, un redactor que escribe y un revisor que valida), este enfoque resulta muy comprensible para perfiles de producto o negocio. El modelo se indica con el prefijo del proveedor (aqui openrouter/). CrewAI exige Python entre 3.10 y 3.13.
5. Claude Agent SDK: 24 lineas
import asyncio, os
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, create_sdk_mcp_server, query, tool
from narzedzia import ZADANIE, INSTRUKCJA, szukaj_plikow, kalkulator, czytaj_strone
def owin(f, param): # funcion de Python -> herramienta para el SDK (devuelve bloques de contenido)
@tool(f.__name__, f.__doc__, {param: str})
async def t(args):
return {"content": [{"type": "text", "text": f(args.get(param, ""))}]}
return t
serwer = create_sdk_mcp_server("faktury", tools=[owin(szukaj_plikow, "fraza"), owin(kalkulator, "wyrazenie"),
owin(czytaj_strone, "url")])
opcje = ClaudeAgentOptions(system_prompt=INSTRUKCJA, model=os.environ.get("CLAUDE_MODEL", "anthropic/claude-haiku-4.5"),
mcp_servers={"faktury": serwer}, strict_mcp_config=True,
tools=[], # sin las herramientas integradas de Claude Code (Bash, Edit, etc.)
allowed_tools=["mcp__faktury__szukaj_plikow", "mcp__faktury__kalkulator",
"mcp__faktury__czytaj_strone"], max_turns=8,
cli_path=os.getenv("CLAUDE_CLI"), # en Windows: ruta al binario claude.exe (no a claude.cmd)
setting_sources=[], # no cargar ~/.claude/settings.json (evita sobreescritura de ANTHROPIC_BASE_URL)
env={"ANTHROPIC_BASE_URL": "https://openrouter.ai/api", # conexion a Claude mediante OpenRouter
"ANTHROPIC_AUTH_TOKEN": os.environ["OPENROUTER_API_KEY"], "ANTHROPIC_API_KEY": ""})
async def main():
async for m in query(prompt=ZADANIE, options=opcje):
if isinstance(m, ResultMessage):
print(m.result)
asyncio.run(main())
Es la configuracion mas densa, dado que Claude Agent SDK integra el motor completo de Claude Code en formato libreria. Las herramientas propias se registran como un servidor MCP en memoria (create_sdk_mcp_server), y las utilidades nativas del sistema (Bash, modificacion de ficheros) se desactivan con tools=[]. Conviene tener presentes tres detalles tecnicos clave detectados durante las pruebas:
- En Windows, el SDK no ejecuta correctamente el archivo
claude.cmdinstalado por npm. Hay que apuntar directamente al binarioclaude.exemediantecli_path; - Si no se define
setting_sources=[], el SDK lee las opciones de~/.claude/settings.jsony puede redirigir las peticiones a un endpoint distinto del especificado en el script (provocando errores HTTP 403); - Para usar OpenRouter, Claude Code debe apuntar a la ruta compatible con Anthropic (
ANTHROPIC_BASE_URL=https://openrouter.ai/api), pasando la clave enANTHROPIC_AUTH_TOKEN.
Comparativa: que framework elegir
| Framework | Curva de aprendizaje | Puntos fuertes | Puntos debiles | Recomendado si |
|---|---|---|---|---|
| Sin framework | La mas directa si dominas Python | Control total, cero dependencias adicionales | Debes implementar cada funcion auxiliar | Estas aprendiendo o tu agente solo utiliza entre 2 y 5 herramientas |
| OpenAI Agents SDK | Suave | Poco código, handoffs, guardrails y trazabilidad nativa | Orientado principalmente a la API de OpenAI | Buscas pasar rápido de un script básico a varios agentes coordinados |
| LangGraph | La mas exigente | Grafo de estados, persistencia y revision humana integrada | Mayor carga conceptual al inicio | El flujo tiene bifurcaciones complejas y exige tolerancia a fallos |
| CrewAI | Suave | Equipos colaborativos con roles; comprensible para perfiles no tecnicos | Instalacion pesada y menor control sobre el bucle interno | Quieres simular equipos de trabajo: investigacion, redaccion y control de calidad |
| Claude Agent SDK | Media | Manejo nativo de archivos y terminal, permisos y subagentes | Limitado a modelos Claude y coste de operacion mas elevado | El agente debe trabajar directamente sobre repositorios o documentos complejos |
Existen más opciones en el ecosistema. Google mantiene ADK (Agent Development Kit, versión 2.11.0 en PyPI), Hugging Face ofrece smolagents (1.26.0) y Microsoft desarrolla Agent Framework. No los incluí en esta tanda de pruebas. Si buscas alternativas sin código (no-code), las herramientas equivalentes son n8n con su nodo AI Agent y Gumloop.
Mi recomendacion practica
- Empieza programando un agente sin frameworks. Una tarde entendiendo el bucle nativo te evitara semanas intentando deducir que hace una libreria por debajo.
- Para tu primer desarrollo serio, utiliza OpenAI Agents SDK. Admite OpenRouter y modelos locales reduciendo la complejidad al minimo.
- Da el salto a LangGraph en cuanto necesites plasmar en papel un diagrama de flujo con bucles, condiciones y puntos de decision complejos.
- Reserva CrewAI y Claude Agent SDK para casos de uso muy concretos: equipos basados en roles o manipulación avanzada de archivos de código.
Preguntas frecuentes
¿LangChain o LangGraph?
LangChain es un catalogo de componentes (modelos, conectores, parsers), mientras que LangGraph gestiona el flujo de control mediante un grafo. En sus versiones 1.x, LangChain utiliza internamente LangGraph para la orquestacion de agentes. Si vas a desarrollar agentes desde cero, empieza directamente por LangGraph y aprovecha de LangChain solo integraciones puntuales como langchain-openai.
¿Son gratuitos estos frameworks para agentes?
Las cinco librerías evaluadas son de código abierto y uso gratuito. Tu único gasto será el consumo de tokens del modelo. Determinados servicios complementarios pueden ser de pago, como LangSmith (monitorización en LangGraph), la nube de CrewAI o las plataformas de trazabilidad de terceros.
¿Que frameworks funcionan con modelos locales?
El bucle propio en Python, OpenAI Agents SDK, LangGraph y CrewAI admiten modelos locales a traves de Ollama o cualquier servidor con API compatible con OpenAI. Claude Agent SDK requiere exclusivamente modelos Claude.
¿Mejora el framework la precision de las respuestas?
En este banco de pruebas, no. Todas las opciones obtuvieron exactamente el mismo resultado valido. La calidad final depende del modelo, de la claridad en las descripciones de las herramientas y de los datos suministrados. El framework aporta arquitectura, control de errores y trazabilidad alrededor del bucle.
¿Cuanto costo ejecutar todos los tests?
Las 16 ejecuciones (15 mediciones y 1 prueba de control) supusieron un gasto acumulado de unos 0,054 EUR (0,060 USD). De esa cifra, 0,052 USD correspondieron a las pruebas con Claude Haiku (alrededor de 0,046 EUR; cambio del BCE a 12/10/2026: 1 EUR = 1,1181 USD).
¿Donde formarse en cada framework?
Hay recursos gratuitos de referencia: LangChain Academy (curso Intro to LangGraph), DeepLearning.AI (AI Agents in LangGraph y Multi AI Agent Systems with crewAI), así como la documentación oficial de OpenAI Agents SDK y Claude Agent SDK. Encontrarás la lista completa y comentada en la sección de formación de nuestra guia.
Google · Tus fuentesBrilla más alto en tu Google - con un solo clicAñadir a fuentes preferidas →Fuentes y fecha de verificacion
- Documentacion oficial consultada: OpenAI Agents SDK, LangChain Academy: Intro to LangGraph, CrewAI docs y Claude Agent SDK (revisados el 4 de octubre de 2026).
- Versiones de paquetes verificadas en PyPI a fecha de 4 de octubre de 2026.
- Mediciones: realizadas en entorno local (Windows 11, Python 3.13) el 4 de octubre de 2026 entre las 13:53 y las 13:57. El código fuente de las distintas variantes se encuentra disponible en el paquete de inicio en la sección starter dentro de la carpeta
frameworki/.


