JamJet
Migrate

Migration von CrewAI

Code-Vergleich und Konzept-Mapping für Entwickler, die von CrewAI zu JamJet wechseln.

Konzept-Mapping

CrewAIJamJet
Agent(role, goal, backstory, tools)@wf.step mit System-Prompt + MCP-Tools
Task(description, agent, context)Workflow-Step — Kontext ist gemeinsamer State
Crew(agents, tasks, process)Workflow
Process.sequentialStandard-Step-Reihenfolge
Process.hierarchicalOrchestrator-Workflow → Sub-Workflows via A2A
crew.kickoff(inputs)wf.run_sync(State(...)) oder jamjet run
crewai_tools.SerperDevToolMCP-Tool-Node (type: tool, server: brave-search)
Memory (short/long term)State-Objekt (kurzfristig); Postgres-gestütztes Runtime (langfristig)
agent.verbose = TrueStrukturiertes Event-Log — jeder Step abfragbar mit jamjet inspect

Side-by-Side-Beispiel

Ein Zwei-Agenten-Crew — Researcher und Writer — arbeiten zusammen, um einen Bericht zu erstellen.

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)

Hauptunterschiede

Agents vs. Steps

CrewAI behandelt Agents als undurchsichtige Objekte mit Rollen, Zielen, Hintergrundgeschichten und Tool-Zugriff. JamJet behandelt diese als das, was sie tatsächlich sind: einen System-Prompt und eine Reihe von Tools. Ihr "Agent" ist ein Step mit einem sorgfältig ausgearbeiteten System-Prompt — Sie haben vollständige Kontrolle und vollständige Transparenz.

Tools

CrewAI hat ein eigenes Tool-Ökosystem (crewai_tools). JamJet verwendet MCP — den offenen Standard. Jeder MCP-Server funktioniert: Brave Search, GitHub, Postgres, Ihr eigener Custom-Server. Kein Vendor-Lock-in an ein proprietäres Tool-Register.

Multi-Agent

CrewAIs Process.hierarchical verwendet einen internen Manager-Agent. JamJet nutzt A2A (Agent-to-Agent-Protokoll) — ein offener Standard, bei dem jeder Agent ein separater Workflow mit eigenem Endpoint ist. Ein Orchestrator delegiert über type: a2a_task-Nodes an Spezialisten. Dies skaliert über Maschinen und Organisationen hinweg.


# orchestrator/workflow.yaml

nodes:
  delegate-research:
    type: a2a_task
    agent_url: "{{ env.RESEARCH_AGENT_URL }}"
    input:
      query: "{{ state.topic }}"
    output_key: research
    next: write-report

Observability

CrewAIs Verbose-Modus gibt menschenlesbaren Text aus. JamJet emittiert strukturierte Events für jeden Step — abfragbar, vergleichbar, wiederholbar:

jamjet inspect exec-abc123   # vollständige Timeline
jamjet events exec-abc123    # Event-Stream

Durability

CrewAI hat keine eingebaute Persistenz. Wenn der Prozess während der Ausführung abstürzt, fangen Sie von vorne an. JamJets Rust-Runtime persistiert jeden Step. Crash Recovery ist automatisch.

Schnellstart-Migration

pip install jamjet
  1. Konvertieren Sie jeden Agent in einen @wf.step — verschieben Sie Rolle/Ziel/Hintergrundgeschichte in den System-Prompt
  2. Konvertieren Sie Task-Reihenfolge in Step-Deklarationsreihenfolge — gemeinsamer Kontext wird zu State-Feldern
  3. Ersetzen Sie crewai_tools durch MCP-Tool-Nodes (type: tool in YAML)
  4. Ersetzen Sie crew.kickoff(inputs) durch wf.run_sync(State(...))
  5. Für Multi-Agent-Hierarchien: verwenden Sie type: a2a_task-Nodes

tip: Vollständige funktionierende Beispiele in jamjet-labs/jamjet-benchmarks.

On this page