Field notesFrameworks

How to Build AI Agents with CrewAI: A Practical Guide with Diagrams

AI agents are useful when a task is too large, repetitive, or multi-step for a single prompt. CrewAI gives you a structured way to assemble a team of specialized agents that research, write, review, and take action. Here is the mental model, the code, and the production checklist.

Most agent frameworks fall into two camps. Either they treat the LLM as the runtime and hide everything else, or they ask you to wire every primitive yourself. CrewAI sits in a useful middle: agents have roles, tasks have expected outputs, and a crew coordinates the work. This guide walks through building a real research-and-writing crew from scratch, with the diagrams and code you need to ship it.

01 What you will build

The example throughout this guide is a simple research-and-writing crew with three specialized agents working in sequence.

  1. A Researcher Agent gathers information on a topic.
  2. A Writer Agent turns the research into a blog draft.
  3. A Reviewer Agent checks clarity, structure, and accuracy.
  4. A Crew coordinates the work in sequence and produces the final output.

It is small on purpose. Once this skeleton works, every other CrewAI concept (tools, memory, flows, hierarchical execution) snaps onto the same structure.

02 The mental model

Before writing code, hold this picture in your head. A crew accepts a user input, dispatches work to agents, each agent runs its task, and outputs flow forward through the pipeline. Tools are optional capabilities attached to specific agents.

flowchart TD
    User[User Input] --> Crew[Crew]

    Crew --> Agent1[Researcher Agent]
    Crew --> Agent2[Writer Agent]
    Crew --> Agent3[Reviewer Agent]

    Agent1 --> Task1[Research Task]
    Agent2 --> Task2[Writing Task]
    Agent3 --> Task3[Review Task]

    Agent1 --> Tools[Tools]
    Tools --> WebSearch[Web Search]
    Tools --> Files[File Reader]
    Tools --> APIs[External APIs]

    Task1 --> Output1[Research Notes]
    Output1 --> Task2
    Task2 --> Output2[Blog Draft]
    Output2 --> Task3
    Task3 --> Final[Final Answer]

The five primitives to remember:

  • Agent. A specialized worker with a role, a goal, and a backstory.
  • Task. A specific assignment with a description and an expected output.
  • Tool. A capability the agent can call (search, file read, API).
  • Crew. The orchestrator that assembles agents and tasks and runs them.
  • Flow. A higher-level controller for branching, state, and multi-crew workflows.

03 Install CrewAI

CrewAI ships with a CLI that scaffolds a working project. A generated project includes agents.yaml, tasks.yaml, a .env file, main.py, crew.py, and directories for tools and knowledge.

uv tool install crewai
crewai create crew research_writer
cd research_writer
crewai install

To run the generated crew:

crewai run

Most projects want the extra tools package as well. It bundles web search, file readers, and other common adapters.

pip install 'crewai[tools]'

04 Define your agents

An agent in CrewAI is defined by three attributes the model uses to stay consistent: a role, a goal, and a backstory. Optional attributes cover the LLM choice, tools, max iterations, and rate limits.

Open src/research_writer/config/agents.yaml:

researcher:
  role: >
    Senior AI Researcher
  goal: >
    Find reliable, concise, and relevant information about the assigned topic.
  backstory: >
    You are an experienced technology researcher who specializes in identifying
    practical trends, useful examples, and credible sources.

writer:
  role: >
    Technical Blog Writer
  goal: >
    Turn research notes into a clear, engaging, beginner-friendly blog post.
  backstory: >
    You write practical technical content for developers and product teams.
    You explain complex ideas with examples, structure, and plain language.

reviewer:
  role: >
    Editorial Reviewer
  goal: >
    Improve the blog for accuracy, readability, structure, and usefulness.
  backstory: >
    You are a careful editor who checks whether the final article is clear,
    complete, and actionable.

The role tells the agent what hat it wears. The goal tells it what success looks like. The backstory shapes voice and judgment. All three matter. Vague roles produce vague work.

05 Define tasks

A CrewAI task is a specific assignment owned by an agent. It carries a description, an expected output, a responsible agent, and optionally a set of tools. Tasks can run sequentially or hierarchically depending on the crew process.

Open src/research_writer/config/tasks.yaml:

research_task:
  description: >
    Research the topic: {topic}.
    Find the main concepts, practical examples, common mistakes, and a simple
    explanation suitable for beginners.
  expected_output: >
    A structured research brief with bullet points, definitions, examples,
    and warnings about common mistakes.
  agent: researcher

writing_task:
  description: >
    Use the research brief to write a complete blog post about {topic}.
    The blog should include an introduction, step-by-step guidance, examples,
    and a conclusion.
  expected_output: >
    A complete markdown blog post.
  agent: writer

review_task:
  description: >
    Review the blog post for clarity, accuracy, structure, and usefulness.
    Improve weak sections and return the final polished version.
  expected_output: >
    A polished final markdown blog post ready to publish.
  agent: reviewer

The single most important field is expected_output. It tells the agent what "done" looks like.

06 Sequential task flow

When you use the sequential process, each task runs in order and its output becomes context for the next. The crew is the orchestrator that owns the inputs, the dispatch, and the final return.

sequenceDiagram
    participant U as User
    participant C as Crew
    participant R as Researcher
    participant W as Writer
    participant E as Reviewer

    U->>C: Provide topic
    C->>R: Run research_task
    R-->>C: Research brief

    C->>W: Run writing_task with research context
    W-->>C: Blog draft

    C->>E: Run review_task
    E-->>C: Final polished blog

    C-->>U: Return final output

Sequential is the right default when each task depends on the previous one. Switch to hierarchical when you want a manager agent to route work based on role and expertise.

07 Wire agents and tasks in crew.py

The crew.py module loads the YAML configuration and assembles the agents, tasks, and process. CrewAI provides decorators that keep the wiring declarative.

from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task


@CrewBase
class ResearchWriterCrew:
    """Research and writing crew."""

    agents_config = "config/agents.yaml"
    tasks_config = "config/tasks.yaml"

    @agent
    def researcher(self) -> Agent:
        return Agent(
            config=self.agents_config["researcher"],
            verbose=True,
        )

    @agent
    def writer(self) -> Agent:
        return Agent(
            config=self.agents_config["writer"],
            verbose=True,
        )

    @agent
    def reviewer(self) -> Agent:
        return Agent(
            config=self.agents_config["reviewer"],
            verbose=True,
        )

    @task
    def research_task(self) -> Task:
        return Task(
            config=self.tasks_config["research_task"],
        )

    @task
    def writing_task(self) -> Task:
        return Task(
            config=self.tasks_config["writing_task"],
        )

    @task
    def review_task(self) -> Task:
        return Task(
            config=self.tasks_config["review_task"],
        )

    @crew
    def crew(self) -> Crew:
        return Crew(
            agents=[
                self.researcher(),
                self.writer(),
                self.reviewer(),
            ],
            tasks=[
                self.research_task(),
                self.writing_task(),
                self.review_task(),
            ],
            process=Process.sequential,
            verbose=True,
        )

08 Run the crew

The entry point is small. It builds inputs, kicks off the crew, and prints the result. Anything more interesting belongs in a Flow (see Section 11).

from research_writer.crew import ResearchWriterCrew


def run():
    inputs = {
        "topic": "How to build AI agents with CrewAI"
    }

    result = ResearchWriterCrew().crew().kickoff(inputs=inputs)
    print(result)


if __name__ == "__main__":
    run()

Then run:

crewai run

09 Add tools

Tools let agents take actions beyond plain text generation. CrewAI ships with adapters for web search, file reading, data analysis, and API calls, and you can write your own for custom business logic.

The researcher agent is a natural fit for search and file tools. Give the writer and reviewer fewer tools so they stay focused on their job.

from crewai import Agent
from crewai_tools import SerperDevTool, FileReadTool

search_tool = SerperDevTool()
file_tool = FileReadTool()

researcher = Agent(
    role="Senior AI Researcher",
    goal="Find reliable information about the assigned topic",
    backstory="You are a careful researcher who checks multiple sources.",
    tools=[search_tool, file_tool],
    verbose=True,
)

10 Agent and tool interaction

When an agent encounters a step it cannot answer from context, it decides whether to call a tool. The tool returns data, the agent reasons over the result, and the loop continues until the task is satisfied.

flowchart LR
    Agent[Researcher Agent] --> Decision{Need external info?}

    Decision -->|Yes| Tool[Search Tool]
    Tool --> Results[Search Results]
    Results --> Agent

    Decision -->|No| Reason[Reason with existing context]
    Reason --> Output[Research Brief]

    Agent --> Output

Two rules of thumb. First, give each agent the smallest set of tools that lets it succeed. Every extra tool adds reasoning surface and cost. Second, set a sensible max iterations cap. Agents that loop forever are the most common source of runaway bills.

11 Crews vs Flows

CrewAI has two orchestration ideas. They are not competitors. They are different layers.

Crews are best when you want autonomous collaboration between role-based agents. The crew picks the order, dispatches work, and aggregates output.

Flows are better when you need structured, event-driven control: state management, branching, retries, checkpoints, human review, or multiple crews working together. Flows are the production wrapper around crews.

flowchart TD
    Start[Application Starts] --> Flow[Flow Controls Execution]

    Flow --> SetTopic[Set Topic]
    SetTopic --> RunCrew[Kick Off Crew]

    RunCrew --> Researcher[Researcher]
    RunCrew --> Writer[Writer]
    RunCrew --> Reviewer[Reviewer]

    Reviewer --> Blog[Final Blog]
    Blog --> Save[Save to File]
    Save --> End[Done]

12 Example flow pattern

A Flow is a class with decorated methods. @start marks the entry point. @listen wires up the next step. State is carried on self.state and persists across steps.

from crewai.flow.flow import Flow, start, listen
from research_writer.crew import ResearchWriterCrew


class BlogFlow(Flow):
    @start()
    def set_topic(self):
        self.state["topic"] = "How to build AI agents with CrewAI"
        return self.state["topic"]

    @listen(set_topic)
    def run_blog_crew(self, topic):
        result = ResearchWriterCrew().crew().kickoff(
            inputs={"topic": topic}
        )
        self.state["blog"] = str(result)
        return self.state["blog"]

    @listen(run_blog_crew)
    def save_blog(self, blog):
        with open("blog.md", "w", encoding="utf-8") as file:
            file.write(blog)
        return "Blog saved to blog.md"


def kickoff():
    BlogFlow().kickoff()

Use Flows the moment your application needs branching, retries, scheduled checkpoints, human review, or coordination across more than one crew. A single sequential crew can run inside a Flow. A Flow cannot run inside a crew.

13 Production checklist

The path from "the demo worked" to "this runs in production" is the same for every CrewAI project. Walk through these phases before you ship.

flowchart TD
    A[Define Business Goal] --> B[Break Goal into Tasks]
    B --> C[Design Specialized Agents]
    C --> D[Assign Tools Carefully]
    D --> E[Choose Process: Sequential or Hierarchical]
    E --> F[Add Guardrails]
    F --> G[Test with Real Inputs]
    G --> H[Log Outputs and Failures]
    H --> I[Deploy and Monitor]

Before deploying, verify:

  • Each agent has one clear responsibility.
  • Each task has a measurable expected output.
  • Tools are only given to agents that need them.
  • Secrets are stored in .env, not in code.
  • Outputs are reviewed before being used in high-risk workflows.
  • Long-running or branching workflows use Flows instead of a bare crew.
  • Iteration caps, timeouts, and cost limits are set on every agent.

14 Common mistakes

Most CrewAI projects fail for the same handful of reasons. They are easy to fix once you can name them.

Creating too many agents

Start with two or three. Add a new agent only when an existing one cannot reasonably cover the responsibility. Five agents that overlap are worse than three that are sharply defined.

Writing vague goals

Bad:

goal: Help with research.

Better:

goal: Find reliable information, summarize key points, and identify practical examples.

Giving every agent every tool

Tools increase power and complexity. They also increase cost. Every tool an agent can see is a tool it might try to use. Be deliberate.

Skipping expected outputs

The expected_output field is how the agent knows when to stop. Use it to define format, length, structure, and quality. Without it, agents either over-deliver or under-deliver, never consistently the right shape.

15 Final architecture

Pulling it all together, here is what a production-ready CrewAI project looks like on disk and at runtime.

flowchart TB
    User[User] --> Input[Topic Input]
    Input --> Main[main.py]

    Main --> CrewFile[crew.py]
    CrewFile --> AgentsYAML[agents.yaml]
    CrewFile --> TasksYAML[tasks.yaml]

    AgentsYAML --> Researcher[Researcher Agent]
    AgentsYAML --> Writer[Writer Agent]
    AgentsYAML --> Reviewer[Reviewer Agent]

    TasksYAML --> ResearchTask[Research Task]
    TasksYAML --> WritingTask[Writing Task]
    TasksYAML --> ReviewTask[Review Task]

    Researcher --> ResearchTask
    ResearchTask --> WritingTask
    Writer --> WritingTask
    WritingTask --> ReviewTask
    Reviewer --> ReviewTask

    ReviewTask --> Output[Final Blog Post]

16 Conclusion

CrewAI gives you a structured way to build multi-agent systems without turning your codebase into a pile of prompts. The basic pattern is simple. Define agents, assign tasks, assemble a crew, give agents tools when needed, and use Flows when the workflow needs more control.

For a first project, build the small sequential crew above: researcher, writer, reviewer. Once it works on real inputs, add tools, then memory, then guardrails, then Flows. That path keeps your agent system understandable while still leaving room to grow into production-grade automation.

Agents are easy to demo. Production agents are software systems. The framework only helps if you treat it that way.

StrivoHow we build it

From CrewAI prototype to production agent system.

At Strivo, we design and build multi-agent systems on CrewAI and other agent frameworks. We handle the tools, evals, guardrails, flow orchestration, and the surrounding software so the agent actually runs in your business, not just on a laptop.