JamJet
Migrate

从 CrewAI 迁移

为从 CrewAI 迁移到 JamJet 的开发者提供的代码对比和概念映射。

概念映射

CrewAIJamJet
Agent(role, goal, backstory, tools)@wf.step 搭配系统提示词 + MCP 工具
Task(description, agent, context)工作流步骤 — 上下文为共享状态
Crew(agents, tasks, process)Workflow
Process.sequential默认步骤顺序
Process.hierarchical编排器工作流 → 通过 A2A 调用子工作流
crew.kickoff(inputs)wf.run_sync(State(...))jamjet run
crewai_tools.SerperDevToolMCP 工具节点 (type: tool, server: brave-search)
Memory (short/long term)State 对象(短期);基于 Postgres 的运行时(长期)
agent.verbose = True结构化事件日志 — 每个步骤可通过 jamjet inspect 查询

对比示例

一个双智能体团队 — 研究员和撰稿人 — 协作生成报告。

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)

核心差异

Agent 与 Step

CrewAI 将 agent 视为具有角色、目标、背景故事和工具访问权限的不透明对象。JamJet 将这些视为它们的本质:一个系统提示词和一组工具。你的「agent」就是一个带有精心设计的系统提示词的 step —— 你拥有完全的控制权和可见性。

工具

CrewAI 有自己的工具生态系统(crewai_tools)。JamJet 使用 MCP —— 开放标准。任何 MCP 服务器都可以工作:Brave Search、GitHub、Postgres,或你自己的自定义服务器。不会被锁定在专有工具注册表中。

多智能体

CrewAI 的 Process.hierarchical 使用内部管理器 agent。JamJet 使用 A2A(Agent-to-Agent 协议)—— 一个开放标准,其中每个 agent 都是具有自己端点的独立工作流。编排器通过 type: a2a_task 节点将任务委托给专家。这种方式可以跨机器和组织扩展。


# 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

可观测性

CrewAI 的详细模式打印人类可读的文本。JamJet 为每个 step 生成结构化事件 —— 可查询、可对比、可重放:

jamjet inspect exec-abc123   # 完整时间线
jamjet events exec-abc123    # 事件流

持久性

CrewAI 没有内置的持久化机制。如果进程在运行中崩溃,你需要重新开始。JamJet 的 Rust 运行时持久化每个 step。崩溃恢复是自动的。

快速迁移指南

pip install jamjet
  1. 将每个 Agent 转换为 @wf.step —— 将角色/目标/背景故事移入系统提示词
  2. Task 顺序转换为 step 声明顺序 —— 共享上下文变成状态字段
  3. 用 MCP 工具节点(YAML 中的 type: tool)替换 crewai_tools
  4. wf.run_sync(State(...)) 替换 crew.kickoff(inputs)
  5. 对于多智能体层级结构:使用 type: a2a_task 节点

提示:jamjet-labs/jamjet-benchmarks 中查看完整的工作示例。

On this page