CrewAI is a Python framework for orchestrating autonomous AI agents. Its core selling point is making multiple Agents work together like a team. It doesn’t depend on LangChain or any other framework; it’s built from the ground up, and the official claim is performance 5x faster than LangGraph. The framework offers two orchestration modes: Crews handle autonomous collaboration, and Flows handle precise workflow control. For scenarios requiring multi-role collaboration (report generation, data analysis, virtual teams), CrewAI’s learning curve is noticeably gentler than LangGraph’s.
Compared to similar frameworks, CrewAI’s strengths are simplicity and independence; its weakness is a relatively young community. LangGraph is more feature-complete but comes with more boilerplate and tight LangChain coupling. Autogen excels at conversational agents but lacks workflow concepts. ChatDev has workflow concepts but limited customization. If you need to quickly stand up a multi-role collaboration system rather than building complex stateful graphs, CrewAI is the lowest-friction option available today.
Core Concepts
CrewAI’s architecture revolves around four concepts: Agent, Task, Crew, and Tools. Understanding their relationships is essential for using the framework.
An Agent represents a role, the most basic execution unit in the system. Each Agent requires a role (identity), goal (objective), and backstory (background story). Backstory determines the Agent’s personality and behavior patterns. You can also specify available tools, which LLM to use, and whether tasks can be delegated to other Agents via allow_delegation.
1 | from crewai import Agent |
A Task defines specific work an Agent must complete, including description (task description), expected_output (expected output format), agent (executor), and output_file (output file path). Tasks and Agents have a many-to-many relationship, but typically one Task binds to one specific Agent.
1 | from crewai import Task |
A Crew is a collection of Agents and Tasks, defining how the entire team collaborates. CrewAI offers two process modes: sequential (tasks execute one after another) suits task chains with clear workflows; hierarchical (automatically assigns a Manager Agent to coordinate) suits scenarios requiring dynamic decision-making.
1 | from crewai import Crew, Process |
Tools extend an Agent’s capability boundary, letting Agents search the web, read/write files, call external APIs, and more. The framework includes a set of built-in tools and supports custom ones.
1 | from crewai_tools import SerperDevTool, FileReadTool |
The overall workflow works like this: you register a set of Agents and a set of Tasks in a Crew, and the Crew assigns Tasks to corresponding Agents based on the selected process mode. In sequential mode, Tasks flow through in definition order; in hierarchical mode, the Manager Agent receives all tasks and dynamically decomposes and distributes them. Each Agent can call its own tools for external information during task execution, passing results to the next step upon completion.
Installation and Environment Setup
CrewAI requires Python 3.10 through 3.13, and uv is the recommended package manager. Basic installation needs only pip install crewai; if you want the built-in tool set (search, file operations, etc.), run pip install 'crewai[tools]'. With uv, the corresponding commands are uv pip install crewai and uv pip install 'crewai[tools]'.
After installation, use the CLI to create a project skeleton:
1 | crewai create crew my_project |
The generated project structure:
1 | my_project/ |
Windows users will likely hit two issues during installation. First, ModuleNotFoundError: tiktoken; fix it by installing embedding dependencies: uv pip install 'crewai[embeddings]'. Second, a Rust compilation error with tiktoken; skip compilation and install the prebuilt package directly: uv pip install tiktoken --prefer-binary. If neither works, you’ll need to install Visual C++ Build Tools first.
Connecting LLM Services
This is where most beginners get stuck. CrewAI defaults to connecting to https://api.openai.com/v1. If you’re using a different LLM service (Alibaba Bailian, DeepSeek, Zhipu, etc.), you must explicitly specify base_url, or you’ll get Connection refused or Invalid API key errors.
CrewAI interfaces with LLMs through LangChain’s ChatModel abstraction, so you essentially need to construct a correct ChatOpenAI or ChatAnthropic instance and pass it to the Agent’s llm parameter. The differences between providers come down to three fields: model name, api_key, and base_url.
OpenAI official is the simplest; no base_url needed:
1 | from langchain_openai import ChatOpenAI |
Anthropic Claude uses a separate package:
1 | from langchain_anthropic import ChatAnthropic |
Alibaba Bailian Coding Plan supports both OpenAI and Anthropic protocols simultaneously, with different base_urls. The OpenAI-compatible endpoint is https://coding.dashscope.aliyuncs.com/v1, and the Anthropic-compatible endpoint is https://coding.dashscope.aliyuncs.com/apps/anthropic. Both protocols can call the Qwen model series; your choice depends on which SDK you prefer.
1 | # OpenAI-compatible protocol |
1 | # Anthropic-compatible protocol |
DeepSeek and Zhipu AI both support the OpenAI protocol; you only need to change base_url. DeepSeek’s address is https://api.deepseek.com/v1, and Zhipu AI’s address is https://open.bigmodel.cn/api/paas/v4/. Local model Ollama works the same way: address is http://localhost:11434/v1, and api_key can be any value.
| Provider | base_url | Compatible Protocol |
|---|---|---|
| OpenAI | Default (no config needed) | Native |
| Anthropic | Default (no config needed) | Native |
| Alibaba Bailian Coding Plan | https://coding.dashscope.aliyuncs.com/v1 |
OpenAI / Anthropic |
| DeepSeek | https://api.deepseek.com/v1 |
OpenAI |
| Zhipu AI | https://open.bigmodel.cn/api/paas/v4/ |
OpenAI |
| Ollama | http://localhost:11434/v1 |
OpenAI |
In production projects, managing provider parameters through a configuration file avoids repeating values in every Agent:
1 | # config/llm_config.py |
One-line invocation when using it; switching models is straightforward:
1 | llm = get_llm() # Default to Alibaba Bailian |
Reference this configuration in an Agent:
1 | from crewai import Agent |
Project Structure Breakdown
CrewAI’s CLI generates a standardized project structure. Understanding each file’s responsibility helps you get up to speed faster.
config/agents.yaml defines all Agent role information. The file uses YAML format to describe each Agent’s role, goal, and backstory, with support for placeholders like {topic} for dynamic runtime substitution.
1 | researcher: |
config/tasks.yaml defines all Task descriptions and expected outputs, also supporting placeholders and dynamic Agent binding.
1 | research_task: |
crew.py is the project core, using a decorator pattern to assemble agents.yaml and tasks.yaml configurations into an executable Crew. @CrewBase marks the class, @agent and @task mark methods, and @crew marks the final Crew assembly method. The framework automatically reads configuration files and injects contents into self.agents_config and self.tasks_config.
1 | from crewai import Agent, Crew, Process, Task |
main.py is the entry point, passing dynamic parameters and launching Crew execution:
1 | from my_crew.crew import MyCrew |
Two ways to run: crewai run (CLI) or python src/my_crew/main.py (direct Python execution).
Hands-On: Building a One-Person Company Agent Team
Suppose you want to develop a “Life Planner” app, but you’re the only person on the team. You can use CrewAI to build a virtual team: a CEO handles decisions and coordination, a CTO handles technical architecture, a Product Manager handles requirements analysis, an Engineer handles code implementation, and a Tester handles quality assurance.
The project splits directories by responsibility. The agents directory holds each role’s definition, tasks holds task definitions, crews holds team collaboration logic, and config holds LLM configuration and project parameters.
1 | life-planner-crew/ |
The LLM configuration strategy is assigning models by role. Decision-making Agents (CEO, CTO) use models with stronger reasoning (like qwen-max); execution Agents (Engineer, Tester) use faster models (like qwen-turbo). This balances cost and quality.
1 | # config/llm_config.py |
The CEO Agent definition needs to be detailed because its backstory directly impacts decision quality. allow_delegation=True lets the CEO delegate tasks to other Agents, which is key in hierarchical mode.
1 | # agents/ceo_agent.py |
The backend engineer uses the efficient model because its tasks lean toward execution rather than decision-making:
1 | # agents/backend_engineer.py |
The Crew assembly uses hierarchical mode, with the CEO acting as the manager role:
1 | # crews/development_crew.py |
Pitfalls and Debugging
LLM connection failures are the most common issue, typically showing as ConnectionError: Failed to connect to api.openai.com. The root cause is forgetting to configure base_url. With Alibaba Bailian, you must explicitly set base_url="https://coding.dashscope.aliyuncs.com/v1"; just filling in api_key isn’t enough.
1 | # Wrong |
Malformed API Keys also trigger authentication failures. Three directions to investigate: check whether the Key was fully copied (no extra spaces or truncation), confirm the environment variable name matches what the code reads, and ensure the .env file loads correctly. Use python-dotenv‘s load_dotenv() to load explicitly, then verify with os.getenv() print:
1 | from dotenv import load_dotenv |
When Agent output doesn’t match expectations, the problem usually lies in the backstory definition. A vague backstory gives the Agent no sense of direction. The more specific the backstory, including tech stack preferences, working principles, and output standards, the more stable the Agent’s behavior.
1 | # Vague — Agent behavior is unpredictable |
For debugging, enabling verbose=True on both Agent and Crew shows the complete execution process, including the Agent’s chain of thought, task assignments, and tool call details. This is invaluable for diagnosing issues.
1 | agent = Agent(role="Analyst", verbose=True) |
Learning Resources
Author: AI Technology Explorer
Date: 2026-03-31Written based on CrewAI v1.12+ and Alibaba Bailian Coding Plan service