Migración desde CrewAI
Comparación de código lado a lado y mapeo de conceptos para desarrolladores que migran de CrewAI a JamJet.
Mapeo de conceptos
| CrewAI | JamJet |
|---|---|
Agent(role, goal, backstory, tools) | @wf.step con system prompt + herramientas MCP |
Task(description, agent, context) | Paso de workflow — el contexto es estado compartido |
Crew(agents, tasks, process) | Workflow |
Process.sequential | Orden de pasos por defecto |
Process.hierarchical | Workflow orquestador → sub-workflows vía A2A |
crew.kickoff(inputs) | wf.run_sync(State(...)) o jamjet run |
crewai_tools.SerperDevTool | Nodo de herramienta MCP (type: tool, server: brave-search) |
| Memory (short/long term) | Objeto State (corto plazo); runtime respaldado por Postgres (largo plazo) |
agent.verbose = True | Log de eventos estructurado — cada paso consultable con jamjet inspect |
Ejemplo lado a lado
Un crew de dos agentes — investigador y redactor — colaborando para producir un informe.
CrewAI
from crewai import Agent, Crew, Process, Task
from crewai_tools import SerperDevTool
search_tool = SerperDevTool()
researcher = Agent(
role="Research Analyst",
goal="Find comprehensive, accurate information on the topic",
backstory="Expert analyst with deep domain knowledge.",
tools=[search_tool],
)
writer = Agent(
role="Technical Writer",
goal="Write clear, concise reports from research findings",
backstory="Skilled writer for technical audiences.",
)
research_task = Task(
description="Research the topic: {topic}",
expected_output="Structured summary with bullet points and sources.",
agent=researcher,
)
write_task = Task(
description="Write a report on: {topic}",
expected_output="Report with introduction, key findings, conclusion.",
agent=writer,
context=[research_task],
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task],
process=Process.sequential,
)
result = crew.kickoff(inputs={"topic": "durable AI workflow orchestration"})JamJet
from openai import OpenAI
from pydantic import BaseModel
from jamjet import Workflow
client = OpenAI()
class State(BaseModel):
topic: str
research: str = ""
report: str = ""
wf = Workflow("research-crew")
@wf.state
class CrewState(State):
pass
@wf.step
async def research(state: CrewState) -> CrewState:
# Role/goal/backstory live in the system prompt — you own it
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": (
"You are an expert research analyst. "
"Return a structured summary with bullet points."
)},
{"role": "user", "content": f"Research: {state.topic}"},
],
)
return state.model_copy(update={"research": resp.choices[0].message.content or ""})
@wf.step
async def write_report(state: CrewState) -> CrewState:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a skilled technical writer."},
{"role": "user", "content": (
f"Topic: {state.topic}\n"
f"Research:\n{state.research}\n"
"Write a comprehensive report."
)},
],
)
return state.model_copy(update={"report": resp.choices[0].message.content or ""})
result = wf.run_sync(CrewState(topic="durable AI workflow orchestration"))
print(result.state.report)Diferencias clave
Agents vs steps
CrewAI trata a los agentes como objetos opacos con roles, objetivos, historias de fondo y acceso a herramientas. JamJet los trata como lo que realmente son: un system prompt y un conjunto de herramientas. Tu "agente" es un step con un system prompt bien elaborado — tienes control total, visibilidad total.
Herramientas
CrewAI tiene su propio ecosistema de herramientas (crewai_tools). JamJet usa MCP — el estándar abierto. Cualquier servidor MCP funciona: Brave Search, GitHub, Postgres, tu propio servidor personalizado. Sin dependencia de un registro de herramientas propietario.
Multi-agente
El Process.hierarchical de CrewAI usa un agente administrador interno. JamJet usa A2A (protocolo Agent-to-Agent) — un estándar abierto donde cada agente es un workflow separado con su propio endpoint. Un orquestador delega a especialistas mediante nodos type: a2a_task. Esto escala entre máquinas y organizaciones.
# orchestrator/workflow.yaml
nodes:
delegate-research:
type: a2a_task
agent_url: "{{ env.RESEARCH_AGENT_URL }}"
input:
query: "{{ state.topic }}"
output_key: research
next: write-reportObservabilidad
El modo verbose de CrewAI imprime texto legible para humanos. JamJet emite eventos estructurados para cada step — consultables, comparables, reproducibles:
jamjet inspect exec-abc123 # línea de tiempo completa
jamjet events exec-abc123 # flujo de eventosDurabilidad
CrewAI no tiene persistencia incorporada. Si el proceso falla a mitad de la ejecución, comienzas de nuevo. El runtime de Rust de JamJet persiste cada step. La recuperación de fallos es automática.
Migración rápida
pip install jamjet- Convierte cada
Agenten un@wf.step— mueve role/goal/backstory al system prompt - Convierte el orden de
Tasken orden de declaración de steps — el contexto compartido se convierte en campos de estado - Reemplaza
crewai_toolscon nodos de herramientas MCP (type: toolen YAML) - Reemplaza
crew.kickoff(inputs)conwf.run_sync(State(...)) - Para jerarquías multi-agente: usa nodos
type: a2a_task
tip: Ejemplos completos y funcionales en jamjet-labs/jamjet-benchmarks.