We use cookies to enhance your experience on the site
CodeWorlds
Back to collections
Guide13 min read

CrewAI, agent teams with a division of roles

CrewAI builds role based agent teams and event driven flows. Crews, Flows, memory, platform pricing, and how it compares with LangGraph.

CrewAI, agent teams with a division of roles

CrewAI describes agent work the way you would describe a team of people: each one gets a role, a goal, and a set of tools, and tasks are divided between them. It is a Python framework under the MIT licence, created in 2023, with a separate commercial platform for deployment.

Two working models worth telling apart

The framework offers two mechanisms, and choosing between them decides whether the project behaves predictably.

Crews are teams of agents working together on a task. You define roles, goals, and tools, and the division of labour follows from the role descriptions. It suits work where the route to a result is not known in advance, analysing a topic from several angles for instance.

Flows are event driven pipelines with explicit state and step ordering. You decide what triggers what and how data passes between stages. It suits processes whose course is fixed and has to be repeatable.

The framework started in 2023 and grew into a project with a large community and a separate deployment platform used inside companies. That matters practically when choosing: documentation and examples are plentiful, and most problems you hit have been described by somebody already. The price of that pace is an API that shifts between versions, so pin the version in your dependency file rather than installing the latest on every build.

The most common beginner mistake is building an agent team where a flow would do. A team costs more, since every agent means separate model calls, and it is harder to diagnose, because you cannot tell which one made the bad call. Start with a flow and reach for a team once step order genuinely depends on the data.

Your first crew

Code
Bash
pip install crewai crewai-tools
export OPENAI_API_KEY=...
Code
Python
from crewai import Agent, Task, Crew, Process

analyst = Agent(
    role="Market analyst",
    goal="Gather facts about competitors in the invoicing tools segment",
    backstory="You work from public data and cite a source for every number.",
    verbose=True,
)

writer = Agent(
    role="Editor",
    goal="Write a concise summary for the board",
    backstory="You write briefly, without jargon, always leading with the conclusion.",
)

research = Task(
    description="Find five competitors and describe their pricing model.",
    expected_output="A list of five companies with prices and a source for each.",
    agent=analyst,
)

summary = Task(
    description="From the gathered data, write a one page memo.",
    expected_output="A memo with the conclusion in the first paragraph.",
    agent=writer,
)

crew = Crew(
    agents=[analyst, writer],
    tasks=[research, summary],
    process=Process.sequential,
)

print(crew.kickoff())

The expected_output field gets skipped often, and it is the most important part of the whole definition. Without it the agent decides for itself what finished means, and results drift between runs. Describe the output format as precisely as you would to a person doing the task for the first time.

How a crew runs

The sequential process executes tasks in order, passing each result as context into the next. It is predictable and cheap, since model calls track task count.

The hierarchical process adds a managing agent that distributes work and reviews results. It performs better on ambiguous tasks, but every handoff is another model call, so the bill grows faster than agent count suggests.

Code
Python
crew = Crew(
    agents=[analyst, writer],
    tasks=[research, summary],
    process=Process.hierarchical,
    manager_llm="gpt-5",
)

A practical note: the managing model can differ from the working ones. Managing needs reasoning, execution often does not, so a stronger model on top and a cheaper one in the tasks can halve the cost with no quality loss.

Tools and memory

An agent without tools can only generate text. Tools give it access to search, files, databases, and your own functions.

Code
Python
from crewai.tools import tool

@tool("Check stock level")
def stock_level(sku: str) -> str:
    """Returns the number of units available for the given SKU."""
    return warehouse.fetch(sku)

analyst = Agent(role="...", goal="...", backstory="...", tools=[stock_level])

The tool description decides whether the agent reaches for it. A sentence stating plainly when to call it works better than one stating merely what it does.

Keep each agent's tool set limited to what its role actually needs. Ten tools on one agent means a longer prompt on every call and more frequent wrong picks, while splitting them across two roles usually improves results at lower cost.

Memory turns on with a single parameter, memory=True on the crew, but its shape changed in the 1.x line. The former three separate layers, short term, long term, and entity memory, are gone. One Memory class replaced them, with scopes arranged in a tree such as /project/alpha, where the model infers the scope and importance of each stored fact and recall blends semantic similarity, recency, and importance. Enable it deliberately, since storage persists across runs and the question of where that data lives comes back, and without your own embedding model it reaches for OpenAI text-embedding-3-large.

That default matters exactly when the question of where storage lives is a real one, since every remembered fact travels to an external vendor for its vector. A self hosted alternative is BGE embeddings, released under a licence permitting commercial use and free of per token cost. You pay for it by hosting the model and with one trap when switching: the vector dimension differs from the default, so an existing store has to be recomputed rather than appended to.

Flows, or when order matters

Flows solve a problem an agent team does not: repeatability. A step fires in response to an event, state passes explicitly between stages, and you know what runs and in what order.

Code
Python
from crewai.flow.flow import Flow, start, listen

class TicketHandling(Flow):
    @start()
    def classify(self):
        return {"category": classifier.run(self.state.content)}

    @listen(classify)
    def route(self, result):
        if result["category"] == "complaint":
            return complaints_crew.kickoff(inputs=result)
        return automatic_reply(result)

This arrangement lets you mix both approaches. The flow handles control and decides what happens, while an agent crew executes the part where the route to a result is not known in advance. That is usually the best compromise between predictability and flexibility.

Keep flow state explicit, in one object, rather than scattered across variables. When diagnosing a fault, answering "what data did this step receive" should take seconds rather than half an hour of log reading.

For longer processes, add error handling at the step level. An external API call that fails once in a hundred runs will, unhandled, stall the whole flow and leave the task in an undefined state.

Pricing

The framework is free under the MIT licence and runs on your own server without restrictions. The paid part is the platform for deploying and monitoring agents.

PlanCostLimitSuited for
Framework on your own infrastructure0 USDnoneFull functionality, MIT licence
AMP platform, Basic plan0 USD50 runs per month, 2 automations, no overageExperiments and a single process
AMP platform, Enterprise plancustom quoteallowance sized to the workflow, overage availableCompliance, SSO, RBAC, deployment in your own VPC

It helps to understand exactly what a platform run counts as. One run is one pass through a process regardless of how many agents take part. The price list has two levels and nothing between them: a Basic plan with fifty runs a month and an Enterprise plan quoted individually. There is no intermediate monthly subscription, so the first step past the free allowance is a sales conversation. What happens at the limit matters more: on Basic those fifty runs are also a hard ceiling, because no overage is sold at that level, and the number of automations is capped at two. Only Enterprise gets an allowance sized to the specific workflow plus overage beyond it. At the volume of an automation reacting to every customer ticket it makes more sense to run the framework on your own infrastructure, where no limit applies, and build monitoring on your side.

The token bill is separate and usually dominates. A crew of four agents with memory can make well over a dozen model calls per task, so price a single run before making a process permanent. At volume, the gap between a pricier and a cheaper model in supporting roles counts in hundreds of dollars a month.

Writing roles so the agent does the right thing

A role description is this framework's equivalent of a system prompt, and it drives output quality more than model choice does. Three elements make the biggest difference.

Scope of competence, meaning what the agent handles and what it does not. A sentence like "you deal only with financial data and pass marketing questions on" prevents an agent answering everything a little.

Way of working, meaning how it should reach a result. "You cite a source for every number" or "you check data currency before answering" changes behaviour more than adding another adjective to the role.

Constraints stated explicitly. Models respond better to clear boundaries than to general encouragement toward care. "You do not guess prices when you cannot find a source, you write no data available" works, "be accurate" does not.

Code
Python
analyst = Agent(
    role="Pricing analyst",
    goal="Establish current competitor prices with a source for each",
    backstory=(
        "You work only from public data. For every price you give the page address "
        "and the date checked. When you cannot find a price, you write 'no data' rather than estimate. "
        "You do not comment on strategy or product quality."
    ),
    max_iter=8,
)

The parameter capping turn count is worth setting from the start. Without it, an agent that cannot close a task keeps trying until the default limit runs out, and every attempt costs.

Treat task descriptions as seriously as role descriptions. A task phrased as "analyse the market" produces a random result, because nothing says when it is finished. A task with a stated output format and item count produces a repeatable one.

CrewAI against the alternatives

ToolStrengthWeaknessPick it when
CrewAILegible role model, fast start, sensible defaultsLess control over flow than a graph givesAgent team with a clear division of work
LangGraphFull control over flow, durable state, pausesMore work on simple casesProcess with branching and human approval
LangChainLargest integration set, agent in one functionMore decisions to makeApplication combining models and tools
n8nVisual interface, hundreds of ready integrationsLess flexible under complex logicAutomation involving non technical people

These tools also combine. An n8n flow can call an agent crew through your own API, and a LangGraph graph can own the stretch that needs a pause for approval.

The choice depends on whether the process describes as a team with roles or as a graph with conditions. For the former CrewAI delivers faster, for the latter a graph is more legible and easier to test.

Two more reference points from the same family are worth knowing. Agno leans on lightness and speed of building an agent, so it often fits better where a team of roles is overkill. CAMEL grew out of research into agents conversing with each other and earns its place when you care about simulation or data generation rather than delivering a production task.

How to tell whether it works

An agent system without measurement looks fine in a demo and fails on real data. Evaluation splits into three questions, each measured differently.

Whether the output has the right format. That is the cheapest measurement and the most often skipped. Twenty runs, checking how many outputs parse or pass downstream without manual fixing, catches most problems with a task description.

Whether the output is factually right. Here you need a set of cases with expected answers, prepared once and run after every change to a role, a task, or a model. It need not be large, thirty cases suffice to notice a regression.

What it cost. Sum model calls and tokens per run, then multiply by expected volume. That number tends to surprise most, because an agent crew consumes many times more than a single call, and the gap stays invisible while the process runs on ten cases.

Turn on verbose logging while tuning and turn it off in production. A run record with prompt text shows where the agent left the path, which with two cooperating roles is rarely obvious. In production the same record costs storage and risks putting data in logs where you do not want it.

Common mistakes

The first is too many agents. Five roles in a first project almost always produces a system where nobody can say which agent made the bad call. Start with one and add a second once the first clearly cannot keep up.

The second is no iteration limit. An agent that cannot close a task will circle until the budget is gone. Set a turn limit and treat hitting it as a bug in the task description.

The third is generic role descriptions. "You are a helpful assistant" gives the model nothing. A role should carry a scope of competence, a way of working, and explicitly stated constraints.

The fourth is having no test set. Changing a role description or a model can improve three cases and break two, and without a comparison list nobody notices until the first complaint.

The fifth is keeping secrets in agent descriptions. Anything written into a role or a task description reaches the prompt and the execution logs.

FAQ

Is CrewAI free?

The framework is open source under the MIT licence and free commercially, with no run limit on your own infrastructure. The paid part is the AMP deployment and monitoring platform, and its price list has only two levels: a Basic plan at 0 USD with 50 runs a month, two automations, and no overage available, and an Enterprise plan quoted individually. No intermediate plan with a published subscription price exists.

CrewAI or LangGraph?

CrewAI delivers faster when the task describes as a team with a division of roles. LangGraph gives full control over flow, durable state, and the ability to pause a process for human approval, so it fits business processes with a fixed course better.

What does one crew run cost?

It depends on agent count, tools, and model. A crew of three agents with memory typically makes eight to twenty model calls per task, so with a mid tier model one run costs tens of cents. Price it across ten real cases before deploying.

Does it work with models other than OpenAI?

Yes, it supports models from various vendors, including Claude and local models served by Ollama. Switching comes down to naming a different model in the agent configuration, though role descriptions usually need retuning afterwards.

Is it production ready?

Yes, under two conditions. The process needs iteration limits and error handling, since without them a failure ends in a silent stall or an invoice. You also need a set of test cases run after every prompt change, because agent behaviour shifts in ways that are hard to notice.

Documentation sits at docs.crewai.com, and the source code in the GitHub repository.