From 2b31e26ba5e277c0233ec69260c7daabdd527afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moura?= Date: Mon, 10 Mar 2025 14:55:09 -0700 Subject: [PATCH] update --- docs/crews.png | Bin 0 -> 29284 bytes docs/flows.png | Bin 0 -> 27052 bytes docs/guides/crews/first-crew.mdx | 313 ++++++++++++++++++ docs/guides/flows/first-flow.mdx | 528 +++++++++++++++++++++++++++++++ docs/introduction.mdx | 88 +++++- 5 files changed, 924 insertions(+), 5 deletions(-) create mode 100644 docs/crews.png create mode 100644 docs/flows.png create mode 100644 docs/guides/crews/first-crew.mdx create mode 100644 docs/guides/flows/first-flow.mdx diff --git a/docs/crews.png b/docs/crews.png new file mode 100644 index 0000000000000000000000000000000000000000..d536e1f2c38fc073257175126565dfd84b342a15 GIT binary patch literal 29284 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 uko>p{8u literal 0 HcmV?d00001 diff --git a/docs/flows.png b/docs/flows.png new file mode 100644 index 0000000000000000000000000000000000000000..becc04856d5512bd9dc0fefa1ddbfd98ce165b84 GIT binary patch literal 27052 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 literal 0 HcmV?d00001 diff --git a/docs/guides/crews/first-crew.mdx b/docs/guides/crews/first-crew.mdx new file mode 100644 index 000000000..767c5166a --- /dev/null +++ b/docs/guides/crews/first-crew.mdx @@ -0,0 +1,313 @@ +--- +title: Build Your First Crew +description: Step-by-step tutorial to create a collaborative AI team that works together to solve complex problems. +icon: users-gear +--- + +# Build Your First Crew + +In this guide, we'll walk through creating a research crew that will help us research and analyze a topic, then create a comprehensive report. This is a practical example of how AI agents can collaborate to accomplish complex tasks. + + + +Before starting, make sure you have: + +1. Installed CrewAI following the [installation guide](/installation) +2. Set up your OpenAI API key in your environment variables +3. Basic understanding of Python + +## Step 1: Create a New CrewAI Project + +First, let's create a new CrewAI project using the CLI: + +```bash +crewai create crew research_crew +cd research_crew +``` + +This will generate a project with the basic structure needed for your crew. The CLI automatically creates: + +- A project directory with the necessary files +- Configuration files for agents and tasks +- A basic crew implementation +- A main script to run the crew + + + CrewAI Framework Overview + + + +## Step 2: Explore the Project Structure + +Let's take a moment to understand the project structure created by the CLI: + +``` +research_crew/ +├── .gitignore +├── pyproject.toml +├── README.md +├── .env +└── src/ + └── research_crew/ + ├── __init__.py + ├── main.py + ├── crew.py + ├── tools/ + │ ├── custom_tool.py + │ └── __init__.py + └── config/ + ├── agents.yaml + └── tasks.yaml +``` + +This structure follows best practices for Python projects and makes it easy to organize your code. + +## Step 3: Configure Your Agents + +Let's modify the `agents.yaml` file to define two specialized agents: a researcher and an analyst. + +```yaml +# src/research_crew/config/agents.yaml +researcher: + role: > + Senior Research Specialist for {topic} + goal: > + Find comprehensive and accurate information about {topic} + with a focus on recent developments and key insights + backstory: > + You are an experienced research specialist with a talent for + finding relevant information from various sources. You excel at + organizing information in a clear and structured manner, making + complex topics accessible to others. + llm: openai/gpt-4o-mini + +analyst: + role: > + Data Analyst and Report Writer for {topic} + goal: > + Analyze research findings and create a comprehensive, well-structured + report that presents insights in a clear and engaging way + backstory: > + You are a skilled analyst with a background in data interpretation + and technical writing. You have a talent for identifying patterns + and extracting meaningful insights from research data, then + communicating those insights effectively through well-crafted reports. + llm: openai/gpt-4o-mini +``` + +## Step 4: Define Your Tasks + +Now, let's modify the `tasks.yaml` file to define the research and analysis tasks: + +```yaml +# src/research_crew/config/tasks.yaml +research_task: + description: > + Conduct thorough research on {topic}. Focus on: + 1. Key concepts and definitions + 2. Historical development and recent trends + 3. Major challenges and opportunities + 4. Notable applications or case studies + 5. Future outlook and potential developments + + Make sure to organize your findings in a structured format with clear sections. + expected_output: > + A comprehensive research document with well-organized sections covering + all the requested aspects of {topic}. Include specific facts, figures, + and examples where relevant. + agent: researcher + +analysis_task: + description: > + Analyze the research findings and create a comprehensive report on {topic}. + Your report should: + 1. Begin with an executive summary + 2. Include all key information from the research + 3. Provide insightful analysis of trends and patterns + 4. Offer recommendations or future considerations + 5. Be formatted in a professional, easy-to-read style with clear headings + expected_output: > + A polished, professional report on {topic} that presents the research + findings with added analysis and insights. The report should be well-structured + with an executive summary, main sections, and conclusion. + agent: analyst + context: + - research_task + output_file: output/report.md +``` + +## Step 5: Configure Your Crew + +Now, let's modify the `crew.py` file to set up our research crew: + +```python +# src/research_crew/crew.py +from crewai import Agent, Crew, Process, Task +from crewai.project import CrewBase, agent, crew, task +from crewai_tools import SerperDevTool + +@CrewBase +class ResearchCrew(): + """Research crew for comprehensive topic analysis and reporting""" + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + verbose=True, + tools=[SerperDevTool()] + ) + + @agent + def analyst(self) -> Agent: + return Agent( + config=self.agents_config['analyst'], + verbose=True + ) + + @task + def research_task(self) -> Task: + return Task( + config=self.tasks_config['research_task'] + ) + + @task + def analysis_task(self) -> Task: + return Task( + config=self.tasks_config['analysis_task'], + output_file='output/report.md' + ) + + @crew + def crew(self) -> Crew: + """Creates the research crew""" + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True, + ) +``` + +## Step 6: Set Up Your Main Script + +Let's modify the `main.py` file to run our crew: + +```python +#!/usr/bin/env python +# src/research_crew/main.py +import os +from research_crew.crew import ResearchCrew + +# Create output directory if it doesn't exist +os.makedirs('output', exist_ok=True) + +def run(): + """ + Run the research crew. + """ + inputs = { + 'topic': 'Artificial Intelligence in Healthcare' + } + + # Create and run the crew + result = ResearchCrew().crew().kickoff(inputs=inputs) + + # Print the result + print("\n\n=== FINAL REPORT ===\n\n") + print(result.raw) + + print("\n\nReport has been saved to output/report.md") + +if __name__ == "__main__": + run() +``` + +## Step 7: Set Up Your Environment Variables + +Create a `.env` file in your project root with your API keys: + +``` +OPENAI_API_KEY=your_openai_api_key +SERPER_API_KEY=your_serper_api_key +``` + +You can get a Serper API key from [Serper.dev](https://serper.dev/). + +## Step 8: Install Dependencies + +Install the required dependencies using the CrewAI CLI: + +```bash +crewai install +``` + +This command will: +1. Read the dependencies from your project configuration +2. Create a virtual environment if needed +3. Install all required packages + +## Step 9: Run Your Crew + +Now, run your crew using the CrewAI CLI: + +```bash +crewai run +``` + +Your crew will start working! The researcher will gather information about the specified topic, and the analyst will create a comprehensive report based on that research. + +## Step 10: Review the Output + +Once the crew completes its work, you'll find the final report in the `output/report.md` file. The report will include: + +1. An executive summary +2. Detailed information about the topic +3. Analysis and insights +4. Recommendations or future considerations + +## Exploring Other CLI Commands + +CrewAI offers several other useful CLI commands for working with crews: + +```bash +# View all available commands +crewai --help + +# Run the crew +crewai run + +# Test the crew +crewai test + +# Reset crew memories +crewai reset-memories + +# Replay from a specific task +crewai replay -t + +# View the latest task outputs +crewai log-tasks-outputs +``` + +## Customizing Your Crew + +You can customize your crew in several ways: + +1. **Add more agents**: Create additional specialized roles like a fact-checker or editor +2. **Modify the process**: Change from `Process.sequential` to `Process.hierarchical` for more complex workflows +3. **Add custom tools**: Create and add specialized tools for your agents +4. **Change the topic**: Update the `topic` parameter in the `inputs` dictionary to research different subjects + +## Next Steps + +Now that you've built your first crew, you can: + +1. Experiment with different agent configurations +2. Try more complex task structures +3. Implement custom tools for your agents +4. Explore [CrewAI Flows](/guides/flows/first-flow) for more advanced workflows + + +Congratulations! You've successfully built your first CrewAI crew that can research and analyze any topic you provide. + \ No newline at end of file diff --git a/docs/guides/flows/first-flow.mdx b/docs/guides/flows/first-flow.mdx new file mode 100644 index 000000000..b030931c3 --- /dev/null +++ b/docs/guides/flows/first-flow.mdx @@ -0,0 +1,528 @@ +--- +title: Build Your First Flow +description: Learn how to create structured, event-driven workflows with precise control over execution. +icon: diagram-project +--- + +# Build Your First Flow + +In this guide, we'll walk through creating a powerful CrewAI Flow that generates a comprehensive learning guide on any topic. This tutorial will demonstrate how Flows provide structured, event-driven control over your AI workflows by combining regular code, direct LLM calls, and crew-based processing. + +## Prerequisites + +Before starting, make sure you have: + +1. Installed CrewAI following the [installation guide](/installation) +2. Set up your OpenAI API key in your environment variables +3. Basic understanding of Python + +## Step 1: Create a New CrewAI Flow Project + +First, let's create a new CrewAI Flow project using the CLI: + +```bash +crewai create flow guide_creator_flow +cd guide_creator_flow +``` + +This will generate a project with the basic structure needed for your flow. + + + CrewAI Framework Overview + + +## Step 2: Understanding the Project Structure + +The generated project has the following structure: + +``` +guide_creator_flow/ +├── .gitignore +├── pyproject.toml +├── README.md +├── .env +├── main.py +├── crews/ +│ └── poem_crew/ +│ ├── config/ +│ │ ├── agents.yaml +│ │ └── tasks.yaml +│ └── poem_crew.py +└── tools/ + └── custom_tool.py +``` + +We'll modify this structure to create our guide creator flow. + +## Step 3: Add a Content Writer Crew + +Let's use the CrewAI CLI to add a content writer crew: + +```bash +crewai flow add-crew content-crew +``` + +This command will automatically create the necessary directories and template files. + +## Step 4: Configure the Content Writer Crew + +Now, let's modify the generated files for the content writer crew: + +1. First, update the agents configuration file: + +```yaml +# src/guide_creator_flow/crews/content_crew/config/agents.yaml +content_writer: + role: > + Educational Content Writer + goal: > + Create engaging, informative content that thoroughly explains the assigned topic + and provides valuable insights to the reader + backstory: > + You are a talented educational writer with expertise in creating clear, engaging + content. You have a gift for explaining complex concepts in accessible language + and organizing information in a way that helps readers build their understanding. + llm: openai/gpt-4o-mini + +content_reviewer: + role: > + Educational Content Reviewer and Editor + goal: > + Ensure content is accurate, comprehensive, well-structured, and maintains + consistency with previously written sections + backstory: > + You are a meticulous editor with years of experience reviewing educational + content. You have an eye for detail, clarity, and coherence. You excel at + improving content while maintaining the original author's voice and ensuring + consistent quality across multiple sections. + llm: openai/gpt-4o-mini +``` + +2. Next, update the tasks configuration file: + +```yaml +# src/guide_creator_flow/crews/content_crew/config/tasks.yaml +write_section_task: + description: > + Write a comprehensive section on the topic: "{section_title}" + + Section description: {section_description} + Target audience: {audience_level} level learners + + Your content should: + 1. Begin with a brief introduction to the section topic + 2. Explain all key concepts clearly with examples + 3. Include practical applications or exercises where appropriate + 4. End with a summary of key points + 5. Be approximately 500-800 words in length + + Format your content in Markdown with appropriate headings, lists, and emphasis. + + Previously written sections: + {previous_sections} + + Make sure your content maintains consistency with previously written sections + and builds upon concepts that have already been explained. + expected_output: > + A well-structured, comprehensive section in Markdown format that thoroughly + explains the topic and is appropriate for the target audience. + agent: content_writer + +review_section_task: + description: > + Review and improve the following section on "{section_title}": + + {draft_content} + + Target audience: {audience_level} level learners + + Previously written sections: + {previous_sections} + + Your review should: + 1. Fix any grammatical or spelling errors + 2. Improve clarity and readability + 3. Ensure content is comprehensive and accurate + 4. Verify consistency with previously written sections + 5. Enhance the structure and flow + 6. Add any missing key information + + Provide the improved version of the section in Markdown format. + expected_output: > + An improved, polished version of the section that maintains the original + structure but enhances clarity, accuracy, and consistency. + agent: content_reviewer + context: + - write_section_task +``` + +3. Now, update the crew implementation file: + +```python +# src/guide_creator_flow/crews/content_crew/content_crew.py +from crewai import Agent, Crew, Process, Task +from crewai.project import CrewBase, agent, crew, task + +@CrewBase +class ContentCrew(): + """Content writing crew""" + + @agent + def content_writer(self) -> Agent: + return Agent( + config=self.agents_config['content_writer'], + verbose=True + ) + + @agent + def content_reviewer(self) -> Agent: + return Agent( + config=self.agents_config['content_reviewer'], + verbose=True + ) + + @task + def write_section_task(self) -> Task: + return Task( + config=self.tasks_config['write_section_task'] + ) + + @task + def review_section_task(self) -> Task: + return Task( + config=self.tasks_config['review_section_task'], + context=[self.write_section_task] + ) + + @crew + def crew(self) -> Crew: + """Creates the content writing crew""" + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True, + ) +``` + +## Step 5: Create the Flow + +Now, let's create our flow in the `main.py` file. This flow will: +1. Get user input for a topic +2. Make a direct LLM call to create a structured guide outline +3. Process each section in parallel using the content writer crew +4. Combine everything into a final document + +```python +#!/usr/bin/env python +import json +from typing import List, Dict +from pydantic import BaseModel, Field +from crewai import LLM +from crewai.flow.flow import Flow, listen, start +from guide_creator_flow.crews.content_crew.content_crew import ContentCrew + +# Define our models for structured data +class Section(BaseModel): + title: str = Field(description="Title of the section") + description: str = Field(description="Brief description of what the section should cover") + +class GuideOutline(BaseModel): + title: str = Field(description="Title of the guide") + introduction: str = Field(description="Introduction to the topic") + target_audience: str = Field(description="Description of the target audience") + sections: List[Section] = Field(description="List of sections in the guide") + conclusion: str = Field(description="Conclusion or summary of the guide") + +# Define our flow state +class GuideCreatorState(BaseModel): + topic: str = "" + audience_level: str = "" + guide_outline: GuideOutline = None + sections_content: Dict[str, str] = {} + +class GuideCreatorFlow(Flow[GuideCreatorState]): + """Flow for creating a comprehensive guide on any topic""" + + @start() + def get_user_input(self): + """Get input from the user about the guide topic and audience""" + print("\n=== Create Your Comprehensive Guide ===\n") + + # Get user input + self.state.topic = input("What topic would you like to create a guide for? ") + + # Get audience level with validation + while True: + audience = input("Who is your target audience? (beginner/intermediate/advanced) ").lower() + if audience in ["beginner", "intermediate", "advanced"]: + self.state.audience_level = audience + break + print("Please enter 'beginner', 'intermediate', or 'advanced'") + + print(f"\nCreating a guide on {self.state.topic} for {self.state.audience_level} audience...\n") + return self.state + + @listen(get_user_input) + def create_guide_outline(self, state): + """Create a structured outline for the guide using a direct LLM call""" + print("Creating guide outline...") + + # Initialize the LLM + llm = LLM(model="openai/gpt-4o-mini", response_format=GuideOutline) + + # Create the messages for the outline + messages = [ + {"role": "system", "content": "You are a helpful assistant designed to output JSON."}, + {"role": "user", "content": f""" + Create a detailed outline for a comprehensive guide on "{state.topic}" for {state.audience_level} level learners. + + The outline should include: + 1. A compelling title for the guide + 2. An introduction to the topic + 3. 4-6 main sections that cover the most important aspects of the topic + 4. A conclusion or summary + + For each section, provide a clear title and a brief description of what it should cover. + """} + ] + + # Make the LLM call with JSON response format + response = llm.call(messages=messages) + + # Parse the JSON response + outline_dict = json.loads(response) + self.state.guide_outline = GuideOutline(**outline_dict) + + # Save the outline to a file + with open("output/guide_outline.json", "w") as f: + json.dump(outline_dict, f, indent=2) + + print(f"Guide outline created with {len(self.state.guide_outline.sections)} sections") + return self.state.guide_outline + + @listen(create_guide_outline) + def write_and_compile_guide(self, outline): + """Write all sections and compile the guide""" + print("Writing guide sections and compiling...") + completed_sections = [] + + # Process sections one by one to maintain context flow + for section in outline.sections: + print(f"Processing section: {section.title}") + + # Build context from previous sections + previous_sections_text = "" + if completed_sections: + previous_sections_text = "# Previously Written Sections\n\n" + for title in completed_sections: + previous_sections_text += f"## {title}\n\n" + previous_sections_text += self.state.sections_content.get(title, "") + "\n\n" + else: + previous_sections_text = "No previous sections written yet." + + # Run the content crew for this section + result = ContentCrew().crew().kickoff(inputs={ + "section_title": section.title, + "section_description": section.description, + "audience_level": self.state.audience_level, + "previous_sections": previous_sections_text, + "draft_content": "" + }) + + # Store the content + self.state.sections_content[section.title] = result.raw + completed_sections.append(section.title) + print(f"Section completed: {section.title}") + + # Compile the final guide + guide_content = f"# {outline.title}\n\n" + guide_content += f"## Introduction\n\n{outline.introduction}\n\n" + + # Add each section in order + for section in outline.sections: + section_content = self.state.sections_content.get(section.title, "") + guide_content += f"\n\n{section_content}\n\n" + + # Add conclusion + guide_content += f"## Conclusion\n\n{outline.conclusion}\n\n" + + # Save the guide + with open("output/complete_guide.md", "w") as f: + f.write(guide_content) + + print("\nComplete guide compiled and saved to output/complete_guide.md") + return "Guide creation completed successfully" + +def kickoff(): + """Run the guide creator flow""" + GuideCreatorFlow().kickoff() + print("\n=== Flow Complete ===") + print("Your comprehensive guide is ready in the output directory.") + print("Open output/complete_guide.md to view it.") + +def plot(): + """Generate a visualization of the flow""" + flow = GuideCreatorFlow() + flow.plot("guide_creator_flow") + print("Flow visualization saved to guide_creator_flow.html") + +if __name__ == "__main__": + kickoff() +``` + +## Step 6: Set Up Your Environment Variables + +Create a `.env` file in your project root with your API keys: + +``` +OPENAI_API_KEY=your_openai_api_key +``` + +## Step 7: Install Dependencies + +Install the required dependencies: + +```bash +crewai install +``` + +## Step 8: Run Your Flow + +Now, run your flow using the CrewAI CLI: + +```bash +crewai flow kickoff +``` + +Your flow will: + +1. Prompt you for a topic and target audience +2. Make a direct LLM call to create a structured guide outline +3. Process each section in parallel using the content writer crew +4. Combine everything into a final comprehensive guide + +This demonstrates the power of flows to orchestrate different types of operations, including user input, direct LLM interactions, and crew-based processing. + +## Step 9: Visualize Your Flow + +You can also generate a visualization of your flow: + +```bash +crewai flow plot +``` + +This will create an HTML file that shows the structure of your flow, which can be helpful for understanding and debugging. + +## Step 10: Review the Output + +Once the flow completes, you'll find two files in the `output` directory: + +1. `guide_outline.json`: Contains the structured outline of the guide +2. `complete_guide.md`: The comprehensive guide with all sections + +## Key Features Demonstrated + +This guide creator flow demonstrates several powerful features of CrewAI: + +1. **User interaction**: The flow collects input directly from the user +2. **Direct LLM calls**: Uses the LLM class for efficient, single-purpose AI interactions +3. **Structured data with Pydantic**: Uses Pydantic models to ensure type safety +4. **Sequential processing with context**: Writes sections in order, providing previous sections for context +5. **Multi-agent crews**: Leverages specialized agents (writer and reviewer) for content creation +6. **State management**: Maintains state across different steps of the process + +## Understanding the Flow Structure + +Let's break down the key components of this flow: + +### 1. Direct LLM Calls + +The flow uses CrewAI's `LLM` class to make direct calls to the language model: + +```python +llm = LLM(model="openai/gpt-4o-mini") +response = llm.call(prompt) +``` + +This is more efficient than using a crew when you need a simple, structured response. + +### 2. Asynchronous Processing + +The flow uses async/await to process multiple sections in parallel: + +```python +@listen(create_guide_outline) +async def write_sections(self, outline): + # ... + section_tasks = [] + for section in outline.sections: + task = self.write_section(section, outline.target_audience) + section_tasks.append(task) + + sections_content = await asyncio.gather(*section_tasks) + # ... +``` + +This significantly speeds up the guide creation process. + +### 3. Multi-Agent Crews + +The flow uses a crew with multiple specialized agents: + +```python +# Content creation crew with writer and reviewer +@agent +def content_writer(self) -> Agent: + return Agent( + config=self.agents_config['content_writer'], + verbose=True + ) + +@agent +def content_reviewer(self) -> Agent: + return Agent( + config=self.agents_config['content_reviewer'], + verbose=True + ) +``` + +This demonstrates how flows can orchestrate crews with multiple specialized agents that work together on complex tasks. + +### 4. Context-Aware Sequential Processing + +The flow processes sections in order, providing previous sections as context: + +```python +# Getting previous sections for context +previous_sections_text = "" +if self.state.completed_sections: + previous_sections_text = "# Previously Written Sections\n\n" + for title in self.state.completed_sections: + previous_sections_text += f"## {title}\n\n" + previous_sections_text += self.state.sections_content.get(title, "") + "\n\n" +``` + +This ensures coherence and continuity throughout the guide. + +## Customizing Your Flow + +You can customize your flow in several ways: + +1. **Add more user inputs**: Collect additional information about the desired guide +2. **Enhance the outline**: Modify the LLM prompt to create more detailed outlines +3. **Add more crews**: Use different crews for different parts of the guide +4. **Add review steps**: Include a review and refinement step for the final guide + +## Next Steps + +Now that you've built your first flow, you can: + +1. Experiment with more complex flow structures +2. Try using `@router()` to create conditional branches +3. Explore the `and_` and `or_` functions for more complex parallel execution +4. Connect your flow to external APIs or services + + +Congratulations! You've successfully built your first CrewAI Flow that combines regular code, direct LLM calls, and crew-based processing to create a comprehensive guide. + \ No newline at end of file diff --git a/docs/introduction.mdx b/docs/introduction.mdx index a626e4362..5d9d5232b 100644 --- a/docs/introduction.mdx +++ b/docs/introduction.mdx @@ -6,20 +6,23 @@ icon: handshake # What is CrewAI? -**CrewAI is a cutting-edge framework for orchestrating autonomous AI agents.** +**CrewAI is a lean, lightning-fast Python framework built entirely from scratch—completely independent of LangChain or other agent frameworks.** -CrewAI enables you to create AI teams where each agent has specific roles, tools, and goals, working together to accomplish complex tasks. +CrewAI empowers developers with both high-level simplicity and precise low-level control, ideal for creating autonomous AI agents tailored to any scenario: -Think of it as assembling your dream team - each member (agent) brings unique skills and expertise, collaborating seamlessly to achieve your objectives. +- **CrewAI Crews**: Optimize for autonomy and collaborative intelligence, enabling you to create AI teams where each agent has specific roles, tools, and goals. +- **CrewAI Flows**: Enable granular, event-driven control, single LLM calls for precise task orchestration and supports Crews natively. -## How CrewAI Works +With over 100,000 developers certified through our community courses, CrewAI is rapidly becoming the standard for enterprise-ready AI automation. + +## How Crews Work Just like a company has departments (Sales, Engineering, Marketing) working together under leadership to achieve business goals, CrewAI helps you create an organization of AI agents with specialized roles collaborating to accomplish complex tasks. - CrewAI Framework Overview + CrewAI Framework Overview | Component | Description | Key Features | @@ -53,12 +56,87 @@ Think of it as assembling your dream team - each member (agent) brings unique sk +## How Flows Work + + + While Crews excel at autonomous collaboration, Flows provide structured automations, offering granular control over workflow execution. Flows ensure tasks are executed reliably, securely, and efficiently, handling conditional logic, loops, and dynamic state management with precision. Flows integrate seamlessly with Crews, enabling you to balance high autonomy with exacting control. + + + + CrewAI Framework Overview + + +| Component | Description | Key Features | +|:----------|:-----------:|:------------| +| **Flow** | Structured workflow orchestration | • Manages execution paths
• Handles state transitions
• Controls task sequencing
• Ensures reliable execution | +| **Events** | Triggers for workflow actions | • Initiate specific processes
• Enable dynamic responses
• Support conditional branching
• Allow for real-time adaptation | +| **States** | Workflow execution contexts | • Maintain execution data
• Enable persistence
• Support resumability
• Ensure execution integrity | +| **Crew Support** | Enhances workflow automation | • Injects pockets of agency when needed
• Complements structured workflows
• Balances automation with intelligence
• Enables adaptive decision-making | + +### Key Capabilities + + + + Define precise execution paths responding dynamically to events + + + Manage workflow states and conditional execution securely and efficiently + + + Effortlessly combine with Crews for enhanced autonomy and intelligence + + + Ensure predictable outcomes with explicit control flow and error handling + + + +## When to Use Crews vs. Flows + + + Understanding when to use Crews versus Flows is key to maximizing the potential of CrewAI in your applications. + + +| Use Case | Recommended Approach | Why? | +|:---------|:---------------------|:-----| +| **Open-ended research** | Crews | When tasks require creative thinking, exploration, and adaptation | +| **Content generation** | Crews | For collaborative creation of articles, reports, or marketing materials | +| **Decision workflows** | Flows | When you need predictable, auditable decision paths with precise control | +| **API orchestration** | Flows | For reliable integration with multiple external services in a specific sequence | +| **Hybrid applications** | Combined approach | Use Flows to orchestrate overall process with Crews handling complex subtasks | + +### Decision Framework + +- **Choose Crews when:** You need autonomous problem-solving, creative collaboration, or exploratory tasks +- **Choose Flows when:** You require deterministic outcomes, auditability, or precise control over execution +- **Combine both when:** Your application needs both structured processes and pockets of autonomous intelligence + ## Why Choose CrewAI? - 🧠 **Autonomous Operation**: Agents make intelligent decisions based on their roles and available tools - 📝 **Natural Interaction**: Agents communicate and collaborate like human team members - 🛠️ **Extensible Design**: Easy to add new tools, roles, and capabilities - 🚀 **Production Ready**: Built for reliability and scalability in real-world applications +- 🔒 **Security-Focused**: Designed with enterprise security requirements in mind +- 💰 **Cost-Efficient**: Optimized to minimize token usage and API calls + +## Ready to Start Building? + + + + Step-by-step tutorial to create a collaborative AI team that works together to solve complex problems. + + + Learn how to create structured, event-driven workflows with precise control over execution. + +