Skip to main content

CubePi vs CrewAI

CrewAI organises your agent system around role-playing metaphors — crews, agents with roles and backstories, and tasks that agents are assigned to. CubePi starts from a different premise: an agent is a plain async while-loop that calls the model, runs tools, and repeats.

If the role-based abstraction is solving a problem you do not have, CubePi removes that layer. Here is how the two compare.

Side-by-side

CrewAICubePi
AbstractionCrews of role-playing agents with roles, goals, and backstoriesA plain async while-loop — readable top to bottom in five minutes
Multi-agentFirst-class: hierarchical or sequential process typesSubagent middleware — spawn child agents, await results, compose freely
AsyncSynchronous by default; async support added laterAsync-first — every entry point is async
StreamingLimited streaming supportasync for event in stream — one pattern, eleven event types
CheckpointingNo built-in persistence layerAppend-only — O(1) DB I/O; backends: memory, SQLite, Postgres, MySQL
Dependencieslangchain-core + many transitive deps3 core deps: pydantic, anthropic, openai
ToolsTool classes with schema boilerplateDecorate any async function with @tool — schema auto-derived
ObservabilityBasic logging; no native OTelNative OpenTelemetry — GenAI semconv, OTLP / JSONL exporters
TestingRequires live API calls for most testsFauxProvider — deterministic streaming, no API keys needed

A tool-using agent

# CrewAI
from crewai import Agent, Task, Crew, Process
from crewai.tools import BaseTool
from pydantic import BaseModel

class WeatherInput(BaseModel):
city: str

class WeatherTool(BaseTool):
name: str = "get_weather"
description: str = "Get current weather for a city."
args_schema: type[BaseModel] = WeatherInput

def _run(self, city: str) -> str:
return f"72F and sunny in {city}"

weather_tool = WeatherTool()

agent = Agent(
role="Weather Assistant",
goal="Answer weather questions accurately.",
backstory="You are a helpful weather assistant.",
tools=[weather_tool],
llm="claude-sonnet-4-6",
)

task = Task(
description="What's the weather in {city}?",
expected_output="A weather report for the city.",
agent=agent,
)

crew = Crew(agents=[agent], tasks=[task], process=Process.sequential)
result = crew.kickoff(inputs={"city": "Tokyo"})
# CubePi
from cubepi import Agent, tool
from cubepi.providers.anthropic import AnthropicProvider


@tool
async def get_weather(city: str) -> str:
"Get current weather for a city."
return f"72F and sunny in {city}"


provider = AnthropicProvider(provider_id="anthropic", api_key="...")
agent = Agent(
model=provider.model("claude-sonnet-4-6"),
tools=[get_weather],
system_prompt="You are a helpful weather assistant.",
)
await agent.prompt("What's the weather in Tokyo?")

Roles, goals, and backstories — or just a system prompt

CrewAI's "role", "goal", and "backstory" fields are a structured way to write a system prompt. When you have one agent doing one job, the role metaphor adds ceremony without adding capability. In CubePi, `system_prompt` is a string you own completely — no framework vocabulary to learn, no structure to maintain.

For genuine multi-agent scenarios, CubePi provides a `SubagentsMiddleware` that spawns child agents and wires their results back to the parent — without the crew/process/task object model.

Persistence that does not require you to wire it yourself

CrewAI does not ship a built-in checkpointing layer. If you want conversations to survive restarts you add your own database logic. CubePi's append-only checkpointing ships out of the box — `SQLiteCheckpointer`, `PostgresCheckpointer`, and `MySQLCheckpointer` each write only the new messages from each turn, so write cost stays O(1) regardless of how long the thread grows.

When CrewAI is the better fit

CrewAI is a reasonable choice if your workflow maps naturally onto the crew metaphor — a team of specialist agents each assigned a discrete task in a pipeline. If you are building a single conversational agent, a stateful assistant, or anything that needs production-grade persistence or OTel observability, CubePi is the leaner path.