diff --git a/docs/concepts/crews.mdx b/docs/concepts/crews.mdx index ec0f190de..3225b48b6 100644 --- a/docs/concepts/crews.mdx +++ b/docs/concepts/crews.mdx @@ -41,6 +41,155 @@ A crew in crewAI represents a collaborative group of agents working together to **Crew Max RPM**: The `max_rpm` attribute sets the maximum number of requests per minute the crew can perform to avoid rate limits and will override individual agents' `max_rpm` settings if you set it. +## Creating Crews + +There are two ways to create crews in CrewAI: using **YAML configuration (recommended)** or defining them **directly in code**. + +### YAML Configuration (Recommended) + +Using YAML configuration provides a cleaner, more maintainable way to define crews and is consistent with how agents and tasks are defined in CrewAI projects. + +After creating your CrewAI project as outlined in the [Installation](/installation) section, you can define your crew in a class that inherits from `CrewBase` and uses decorators to define agents, tasks, and the crew itself. + +#### Example Crew Class with Decorators + +```python code +from crewai import Agent, Crew, Task, Process +from crewai.project import CrewBase, agent, task, crew, before_kickoff, after_kickoff + + +@CrewBase +class YourCrewName: + """Description of your crew""" + + # Paths to your YAML configuration files + # To see an example agent and task defined in YAML, checkout the following: + # - Task: https://docs.crewai.com/concepts/tasks#yaml-configuration-recommended + # - Agents: https://docs.crewai.com/concepts/agents#yaml-configuration-recommended + agents_config = 'config/agents.yaml' + tasks_config = 'config/tasks.yaml' + + @before_kickoff + def prepare_inputs(self, inputs): + # Modify inputs before the crew starts + inputs['additional_data'] = "Some extra information" + return inputs + + @after_kickoff + def process_output(self, output): + # Modify output after the crew finishes + output.raw += "\nProcessed after kickoff." + return output + + @agent + def agent_one(self) -> Agent: + return Agent( + config=self.agents_config['agent_one'], + verbose=True + ) + + @agent + def agent_two(self) -> Agent: + return Agent( + config=self.agents_config['agent_two'], + verbose=True + ) + + @task + def task_one(self) -> Task: + return Task( + config=self.tasks_config['task_one'] + ) + + @task + def task_two(self) -> Task: + return Task( + config=self.tasks_config['task_two'] + ) + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, # Automatically collected by the @agent decorator + tasks=self.tasks, # Automatically collected by the @task decorator. + process=Process.sequential, + verbose=True, + ) +``` + + +Tasks will be executed in the order they are defined. + + +The `CrewBase` class, along with these decorators, automates the collection of agents and tasks, reducing the need for manual management. + +#### Decorators overview from `annotations.py` + +CrewAI provides several decorators in the `annotations.py` file that are used to mark methods within your crew class for special handling: + +- `@CrewBase`: Marks the class as a crew base class. +- `@agent`: Denotes a method that returns an `Agent` object. +- `@task`: Denotes a method that returns a `Task` object. +- `@crew`: Denotes the method that returns the `Crew` object. +- `@before_kickoff`: (Optional) Marks a method to be executed before the crew starts. +- `@after_kickoff`: (Optional) Marks a method to be executed after the crew finishes. + +These decorators help in organizing your crew's structure and automatically collecting agents and tasks without manually listing them. + +### Direct Code Definition (Alternative) + +Alternatively, you can define the crew directly in code without using YAML configuration files. + +```python code +from crewai import Agent, Crew, Task, Process +from crewai_tools import YourCustomTool + +class YourCrewName: + def agent_one(self) -> Agent: + return Agent( + role="Data Analyst", + goal="Analyze data trends in the market", + backstory="An experienced data analyst with a background in economics", + verbose=True, + tools=[YourCustomTool()] + ) + + def agent_two(self) -> Agent: + return Agent( + role="Market Researcher", + goal="Gather information on market dynamics", + backstory="A diligent researcher with a keen eye for detail", + verbose=True + ) + + def task_one(self) -> Task: + return Task( + description="Collect recent market data and identify trends.", + expected_output="A report summarizing key trends in the market.", + agent=self.agent_one() + ) + + def task_two(self) -> Task: + return Task( + description="Research factors affecting market dynamics.", + expected_output="An analysis of factors influencing the market.", + agent=self.agent_two() + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.agent_one(), self.agent_two()], + tasks=[self.task_one(), self.task_two()], + process=Process.sequential, + verbose=True + ) +``` + +In this example: + +- Agents and tasks are defined directly within the class without decorators. +- We manually create and manage the list of agents and tasks. +- This approach provides more control but can be less maintainable for larger projects. ## Crew Output @@ -188,4 +337,4 @@ Then, to replay from a specific task, use: crewai replay -t ``` -These commands let you replay from your latest kickoff tasks, still retaining context from previously executed tasks. \ No newline at end of file +These commands let you replay from your latest kickoff tasks, still retaining context from previously executed tasks. diff --git a/src/crewai/cli/templates/crew/crew.py b/src/crewai/cli/templates/crew/crew.py index 0a8c7481a..383bfac48 100644 --- a/src/crewai/cli/templates/crew/crew.py +++ b/src/crewai/cli/templates/crew/crew.py @@ -1,37 +1,26 @@ from crewai import Agent, Crew, Process, Task -from crewai.project import CrewBase, agent, crew, task, before_kickoff, after_kickoff -# Uncomment the following line to use an example of a custom tool -# from {{folder_name}}.tools.custom_tool import MyCustomTool -# Uncomment the following line to use an example of a knowledge source -# from crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource +from crewai.project import CrewBase, agent, crew, task -# Check our tools documentations for more information on how to use them -# from crewai_tools import SerperDevTool +# If you want to run a snippet of code before or after the crew starts, +# you can use the @before_kickoff and @after_kickoff decorators +# https://docs.crewai.com/concepts/crews#example-crew-class-with-decorators @CrewBase class {{crew_name}}(): """{{crew_name}} crew""" + # Learn more about YAML configuration files here: + # Agents: https://docs.crewai.com/concepts/agents#yaml-configuration-recommended + # Tasks: https://docs.crewai.com/concepts/tasks#yaml-configuration-recommended agents_config = 'config/agents.yaml' tasks_config = 'config/tasks.yaml' - @before_kickoff # Optional hook to be executed before the crew starts - def pull_data_example(self, inputs): - # Example of pulling data from an external API, dynamically changing the inputs - inputs['extra_data'] = "This is extra data" - return inputs - - @after_kickoff # Optional hook to be executed after the crew has finished - def log_results(self, output): - # Example of logging results, dynamically changing the output - print(f"Results: {output}") - return output - + # If you would like to add tools to your agents, you can learn more about it here: + # https://docs.crewai.com/concepts/agents#agent-tools @agent def researcher(self) -> Agent: return Agent( config=self.agents_config['researcher'], - # tools=[MyCustomTool()], # Example of custom tool, loaded on the beginning of file verbose=True ) @@ -42,6 +31,9 @@ class {{crew_name}}(): verbose=True ) + # To learn more about structured task outputs, + # task dependencies, and task callbacks, check out the documentation: + # https://docs.crewai.com/concepts/tasks#overview-of-a-task @task def research_task(self) -> Task: return Task( @@ -58,14 +50,8 @@ class {{crew_name}}(): @crew def crew(self) -> Crew: """Creates the {{crew_name}} crew""" - # You can add knowledge sources here - # knowledge_path = "user_preference.txt" - # sources = [ - # TextFileKnowledgeSource( - # file_path="knowledge/user_preference.txt", - # metadata={"preference": "personal"} - # ), - # ] + # To learn how to add knowledge sources to your crew, check out the documentation: + # https://docs.crewai.com/concepts/knowledge#what-is-knowledge return Crew( agents=self.agents, # Automatically created by the @agent decorator @@ -73,5 +59,4 @@ class {{crew_name}}(): process=Process.sequential, verbose=True, # process=Process.hierarchical, # In case you wanna use that instead https://docs.crewai.com/how-to/Hierarchical/ - # knowledge_sources=sources, # In the case you want to add knowledge sources ) diff --git a/src/crewai/cli/templates/flow/crews/poem_crew/poem_crew.py b/src/crewai/cli/templates/flow/crews/poem_crew/poem_crew.py index cc3ce7150..5e978d985 100644 --- a/src/crewai/cli/templates/flow/crews/poem_crew/poem_crew.py +++ b/src/crewai/cli/templates/flow/crews/poem_crew/poem_crew.py @@ -1,31 +1,47 @@ from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task +# If you want to run a snippet of code before or after the crew starts, +# you can use the @before_kickoff and @after_kickoff decorators +# https://docs.crewai.com/concepts/crews#example-crew-class-with-decorators + + @CrewBase -class PoemCrew(): - """Poem Crew""" +class PoemCrew: + """Poem Crew""" - agents_config = 'config/agents.yaml' - tasks_config = 'config/tasks.yaml' + # Learn more about YAML configuration files here: + # Agents: https://docs.crewai.com/concepts/agents#yaml-configuration-recommended + # Tasks: https://docs.crewai.com/concepts/tasks#yaml-configuration-recommended + agents_config = "config/agents.yaml" + tasks_config = "config/tasks.yaml" - @agent - def poem_writer(self) -> Agent: - return Agent( - config=self.agents_config['poem_writer'], - ) + # If you would lik to add tools to your crew, you can learn more about it here: + # https://docs.crewai.com/concepts/agents#agent-tools + @agent + def poem_writer(self) -> Agent: + return Agent( + config=self.agents_config["poem_writer"], + ) - @task - def write_poem(self) -> Task: - return Task( - config=self.tasks_config['write_poem'], - ) + # To learn more about structured task outputs, + # task dependencies, and task callbacks, check out the documentation: + # https://docs.crewai.com/concepts/tasks#overview-of-a-task + @task + def write_poem(self) -> Task: + return Task( + config=self.tasks_config["write_poem"], + ) - @crew - def crew(self) -> Crew: - """Creates the Research Crew""" - return Crew( - agents=self.agents, # Automatically created by the @agent decorator - tasks=self.tasks, # Automatically created by the @task decorator - process=Process.sequential, - verbose=True, - ) + @crew + def crew(self) -> Crew: + """Creates the Research Crew""" + # To learn how to add knowledge sources to your crew, check out the documentation: + # https://docs.crewai.com/concepts/knowledge#what-is-knowledge + + return Crew( + agents=self.agents, # Automatically created by the @agent decorator + tasks=self.tasks, # Automatically created by the @task decorator + process=Process.sequential, + verbose=True, + )