Compare commits

...

11 Commits

Author SHA1 Message Date
Eduardo Chiarotti
d0bb808873 feat: change log to inside function 2024-07-11 16:47:43 -03:00
Eduardo Chiarotti
852c88f94a feat: refactor and improve code for planning feature 2024-07-11 16:45:24 -03:00
Eduardo Chiarotti
2c2193cda3 feat: add planning feature to Crew 2024-07-10 16:51:37 -03:00
João Moura
691b094a40 adding new docs 2024-07-08 03:15:14 -04:00
prime-computing-lab
68e9e54c88 Update MDXSearchTool.md (#745)
description fixed to markdown language instead of marketing search
2024-07-08 02:21:00 -03:00
João Moura
d0d99125c4 updating crewAI-tools verison 2024-07-08 01:17:22 -04:00
Taleb
129000d01f Performed spell check across most of code base (#882)
* Performed spell check across the entire documentation

Thank you once again!

* Performed spell check across the most of code base
Folders been checked:
- agents
- cli
- memory
- project
- tasks
- telemetry
- tools
- translations
2024-07-07 13:00:05 -03:00
WellyngtonF
47f9d026dd passing cloned agents when copying context (#885) 2024-07-07 12:58:38 -03:00
Gui Vieira
b75b0b5552 Emit task created (#875)
* Emit task created

* Limit data to shared crews
2024-07-07 12:58:24 -03:00
João Moura
3dd6249f1e TYPO 2024-07-06 20:03:54 -04:00
João Moura
8451113039 new docs 2024-07-06 16:32:00 -04:00
16 changed files with 338 additions and 45 deletions

View File

@@ -0,0 +1,31 @@
---
title: Forcing Tool Output as Result
description: Learn how to force tool output as the result in of an Agent's task in crewAI.
---
## Introduction
In CrewAI, you can force the output of a tool as the result of an agent's task. This feature is useful when you want to ensure that the tool output is captured and returned as the task result, and avoid the agent modifying the output during the task execution.
## Forcing Tool Output as Result
To force the tool output as the result of an agent's task, you can set the `force_tool_output` parameter to `True` when creating the task. This parameter ensures that the tool output is captured and returned as the task result, without any modifications by the agent.
Here's an example of how to force the tool output as the result of an agent's task:
```python
# ...
# Define a custom tool that returns the result as the answer
coding_agent =Agent(
role="Data Scientist",
goal="Product amazing resports on AI",
backstory="You work with data and AI",
tools=[MyCustomTool(result_as_answer=True)],
)
# ...
```
### Workflow in Action
1. **Task Execution**: The agent executes the task using the tool provided.
2. **Tool Output**: The tool generates the output, which is captured as the task result.
3. **Agent Interaction**: The agent my reflect and take learnings from the tool but the output is not modified.
4. **Result Return**: The tool output is returned as the task result without any modifications.

View File

@@ -0,0 +1,137 @@
---
title: Starting a New CrewAI Project
description: A comprehensive guide to starting a new CrewAI project, including the latest updates and project setup methods.
---
# Starting Your CrewAI Project
Welcome to the ultimate guide for starting a new CrewAI project. This document will walk you through the steps to create, customize, and run your CrewAI project, ensuring you have everything you need to get started.
## Prerequisites
We assume you have already installed CrewAI. If not, please refer to the [installation guide](how-to/Installing-CrewAI.md) to install CrewAI and its dependencies.
## Creating a New Project
To create a new project, run the following CLI command:
```shell
$ crewai create my_project
```
This command will create a new project folder with the following structure:
```shell
my_project/
├── .gitignore
├── pyproject.toml
├── README.md
└── src/
└── my_project/
├── __init__.py
├── main.py
├── crew.py
├── tools/
│ ├── custom_tool.py
│ └── __init__.py
└── config/
├── agents.yaml
└── tasks.yaml
```
You can now start developing your project by editing the files in the `src/my_project` folder. The `main.py` file is the entry point of your project, and the `crew.py` file is where you define your agents and tasks.
## Customizing Your Project
To customize your project, you can:
- Modify `src/my_project/config/agents.yaml` to define your agents.
- Modify `src/my_project/config/tasks.yaml` to define your tasks.
- Modify `src/my_project/crew.py` to add your own logic, tools, and specific arguments.
- Modify `src/my_project/main.py` to add custom inputs for your agents and tasks.
- Add your environment variables into the `.env` file.
### Example: Defining Agents and Tasks
#### agents.yaml
```yaml
researcher:
role: >
Job Candidate Researcher
goal: >
Find potential candidates for the job
backstory: >
You are adept at finding the right candidates by exploring various online
resources. Your skill in identifying suitable candidates ensures the best
match for job positions.
```
#### tasks.yaml
```yaml
research_candidates_task:
description: >
Conduct thorough research to find potential candidates for the specified job.
Utilize various online resources and databases to gather a comprehensive list of potential candidates.
Ensure that the candidates meet the job requirements provided.
Job Requirements:
{job_requirements}
expected_output: >
A list of 10 potential candidates with their contact information and brief profiles highlighting their suitability.
```
## Installing Dependencies
To install the dependencies for your project, you can use Poetry. First, navigate to your project directory:
```shell
$ cd my_project
$ poetry lock
$ poetry install
```
This will install the dependencies specified in the `pyproject.toml` file.
## Interpolating Variables
Any variable interpolated in your `agents.yaml` and `tasks.yaml` files like `{variable}` will be replaced by the value of the variable in the `main.py` file.
#### agents.yaml
```yaml
research_task:
description: >
Conduct a thorough research about the customer and competitors in the context
of {customer_domain}.
Make sure you find any interesting and relevant information given the
current year is 2024.
expected_output: >
A complete report on the customer and their customers and competitors,
including their demographics, preferences, market positioning and audience engagement.
```
#### main.py
```python
# main.py
def run():
inputs = {
"customer_domain": "crewai.com"
}
MyProjectCrew(inputs).crew().kickoff(inputs=inputs)
```
## Running Your Project
To run your project, use the following command:
```shell
$ poetry run my_project
```
This will initialize your crew of AI agents and begin task execution as defined in your configuration in the `main.py` file.
## Deploying Your Project
The easiest way to deploy your crew is through [CrewAI+](https://www.crewai.com/crewaiplus), where you can deploy your crew in a few clicks.

View File

@@ -48,6 +48,11 @@ Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By
<div style="width:30%">
<h2>How-To Guides</h2>
<ul>
<li>
<a href="./how-to/Start-a-New-CrewAI-Project">
Starting Your crewAI Project
</a>
</li>
<li>
<a href="./how-to/Installing-CrewAI">
Installing crewAI
@@ -88,6 +93,11 @@ Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By
Coding Agents
</a>
</li>
<li>
<a href="./how-to/Force-Tool-Ouput-as-Result">
Forcing Tool Output as Result
</a>
</li>
<li>
<a href="./how-to/Human-Input-on-Execution">
Human Input on Execution

View File

@@ -4,7 +4,7 @@
The MDXSearchTool is in continuous development. Features may be added or removed, and functionality could change unpredictably as we refine the tool.
## Description
The MDX Search Tool is a component of the `crewai_tools` package aimed at facilitating advanced market data extraction. This tool is invaluable for researchers and analysts seeking quick access to market insights, especially within the AI sector. It simplifies the task of acquiring, interpreting, and organizing market data by interfacing with various data sources.
The MDX Search Tool is a component of the `crewai_tools` package aimed at facilitating advanced markdown language extraction. It enables users to effectively search and extract relevant information from MD files using query-based searches. This tool is invaluable for data analysis, information management, and research tasks, streamlining the process of finding specific information within large document collections.
## Installation
Before using the MDX Search Tool, ensure the `crewai_tools` package is installed. If it is not, you can install it with the following command:
@@ -59,4 +59,4 @@ tool = MDXSearchTool(
),
)
)
```
```

View File

@@ -131,6 +131,7 @@ nav:
- Using LangChain Tools: 'core-concepts/Using-LangChain-Tools.md'
- Using LlamaIndex Tools: 'core-concepts/Using-LlamaIndex-Tools.md'
- How to Guides:
- Starting Your crewAI Project: 'how-to/Start-a-New-CrewAI-Project.md'
- Installing CrewAI: 'how-to/Installing-CrewAI.md'
- Getting Started: 'how-to/Creating-a-Crew-and-kick-it-off.md'
- Create Custom Tools: 'how-to/Create-Custom-Tools.md'
@@ -140,6 +141,7 @@ nav:
- Connecting to any LLM: 'how-to/LLM-Connections.md'
- Customizing Agents: 'how-to/Customizing-Agents.md'
- Coding Agents: 'how-to/Coding-Agents.md'
- Forcing Tool Output as Result: 'how-to/Force-Tool-Ouput-as-Result.md'
- Human Input on Execution: 'how-to/Human-Input-on-Execution.md'
- Kickoff a Crew Asynchronously: 'how-to/Kickoff-async.md'
- Kickoff a Crew for a List: 'how-to/Kickoff-for-each.md'

43
poetry.lock generated
View File

@@ -840,13 +840,13 @@ files = [
[[package]]
name = "crewai-tools"
version = "0.4.7"
version = "0.4.8"
description = "Set of tools for the crewAI framework"
optional = false
python-versions = "<=3.13,>=3.10"
files = [
{file = "crewai_tools-0.4.7-py3-none-any.whl", hash = "sha256:3ff04b2da07d2c48e72f898511295b4a10038dd3e4fe859baa93fec1fb8baf8e"},
{file = "crewai_tools-0.4.7.tar.gz", hash = "sha256:4502a5e0ab94a7dae6638d000768f80049918909ca5338cdebc280351b3ce003"},
{file = "crewai_tools-0.4.8-py3-none-any.whl", hash = "sha256:628b08515ee0e06c751da1dd66b0cff70c9b2644775891c8f59883cb5debfef4"},
{file = "crewai_tools-0.4.8.tar.gz", hash = "sha256:ae190bd187f980163523c86ee7e1eb2ed78896f935d6caff98908dd7ab6c982b"},
]
[package.dependencies]
@@ -1054,13 +1054,13 @@ idna = ">=2.0.0"
[[package]]
name = "embedchain"
version = "0.1.115"
version = "0.1.116"
description = "Simplest open source retrieval (RAG) framework"
optional = false
python-versions = "<=3.13,>=3.9"
files = [
{file = "embedchain-0.1.115-py3-none-any.whl", hash = "sha256:6f1842edea7780e6b1d21d073b72b2c916f440411c32e758165c88141b2ac1ec"},
{file = "embedchain-0.1.115.tar.gz", hash = "sha256:8b259a3307e022924c99cf82b17789f141d157f11e53beb3bc82bf49efa2e31e"},
{file = "embedchain-0.1.116-py3-none-any.whl", hash = "sha256:388835d047f9ff4542ebf50e3fa633ef596db262cbe506195ee4976b91a49172"},
{file = "embedchain-0.1.116.tar.gz", hash = "sha256:3e4d6418df2e749c2bd3cd3153c3857cbecd7227afe40b87d5ac3df629c394b2"},
]
[package.dependencies]
@@ -1075,6 +1075,7 @@ langchain = ">0.2,<=0.3"
langchain-cohere = ">=0.1.4,<0.2.0"
langchain-community = ">=0.2.6,<0.3.0"
langchain-openai = ">=0.1.7,<0.2.0"
memzero = ">=0.0.7,<0.0.8"
openai = ">=1.1.1"
posthog = ">=3.0.2,<4.0.0"
pypdf = ">=4.0.1,<5.0.0"
@@ -2051,13 +2052,13 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve
[[package]]
name = "identify"
version = "2.5.36"
version = "2.6.0"
description = "File identification library for Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"},
{file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"},
{file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"},
{file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"},
]
[package.extras]
@@ -2498,13 +2499,13 @@ langchain-core = ">=0.2.10,<0.3.0"
[[package]]
name = "langsmith"
version = "0.1.83"
version = "0.1.84"
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
optional = false
python-versions = "<4.0,>=3.8.1"
files = [
{file = "langsmith-0.1.83-py3-none-any.whl", hash = "sha256:f54d8cd8479b648b6339f3f735d19292c3516d080f680933ecdca3eab4b67ed3"},
{file = "langsmith-0.1.83.tar.gz", hash = "sha256:5cdd947212c8ad19adb992c06471c860185a777daa6859bb47150f90daf64bf3"},
{file = "langsmith-0.1.84-py3-none-any.whl", hash = "sha256:01f3c6390dba26c583bac8dd0e551ce3d0509c7f55cad714db0b5c8d36e4c7ff"},
{file = "langsmith-0.1.84.tar.gz", hash = "sha256:5220c0439838b9a5bd320fd3686be505c5083dcee22d2452006c23891153bea1"},
]
[package.dependencies]
@@ -2672,6 +2673,22 @@ files = [
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
]
[[package]]
name = "memzero"
version = "0.0.7"
description = "Long-term memory for AI Agents"
optional = false
python-versions = "<4.0,>=3.9"
files = [
{file = "memzero-0.0.7-py3-none-any.whl", hash = "sha256:65f6da88d46263dbc05621fcd01bd09616d0e7f082d55ed9899dc2152491ffd2"},
{file = "memzero-0.0.7.tar.gz", hash = "sha256:0c1f413d8ee0ade955fe9f8b8f5aff2cf58bc94869537aca62139db3d9f50725"},
]
[package.dependencies]
httpx = ">=0.27.0,<0.28.0"
posthog = ">=3.5.0,<4.0.0"
pydantic = ">=2.7.3,<3.0.0"
[[package]]
name = "mergedeep"
version = "1.3.4"
@@ -6073,4 +6090,4 @@ tools = ["crewai-tools"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<=3.13"
content-hash = "4f3e5fddb5f0fc8fd143a8abe947ecac443213d595bd0eeed745ccb82dac2312"
content-hash = "0dbf6f6e2e841fb3eec4ff87ea5d6b430f29702118fee91307983c6b2581e59e"

View File

@@ -21,7 +21,7 @@ opentelemetry-sdk = "^1.22.0"
opentelemetry-exporter-otlp-proto-http = "^1.22.0"
instructor = "1.3.3"
regex = "^2023.12.25"
crewai-tools = { version = "^0.4.7", optional = true }
crewai-tools = { version = "^0.4.8", optional = true }
click = "^8.1.7"
python-dotenv = "^1.0.0"
appdirs = "^1.4.4"
@@ -45,7 +45,7 @@ mkdocs-material = { extras = ["imaging"], version = "^9.5.7" }
mkdocs-material-extensions = "^1.3.1"
pillow = "^10.2.0"
cairosvg = "^2.7.1"
crewai-tools = "^0.4.7"
crewai-tools = "^0.4.8"
[tool.poetry.group.test.dependencies]
pytest = "^8.0.0"

View File

@@ -27,7 +27,7 @@ class OutputConverter(BaseModel, ABC):
model: Any = Field(description="The model to be used to convert the text.")
instructions: str = Field(description="Conversion instructions to the LLM.")
max_attempts: Optional[int] = Field(
description="Max number of attempts to try to get the output formated.",
description="Max number of attempts to try to get the output formatted.",
default=3,
)

View File

@@ -12,4 +12,4 @@ reporting_task:
Make sure the report is detailed and contains any and all relevant information.
expected_output: >
A fully fledge reports with the mains topics, each with a full section of information.
Formated as markdown with out '```'
Formatted as markdown without '```'

View File

@@ -30,6 +30,7 @@ from crewai.tools.agent_tools import AgentTools
from crewai.utilities import I18N, FileHandler, Logger, RPMController
from crewai.utilities.constants import TRAINED_AGENTS_DATA_FILE, TRAINING_DATA_FILE
from crewai.utilities.evaluators.task_evaluator import TaskEvaluator
from crewai.utilities.planning_handler import CrewPlanner
from crewai.utilities.training_handler import CrewTrainingHandler
try:
@@ -133,6 +134,10 @@ class Crew(BaseModel):
default=False,
description="output_log_file",
)
planning: Optional[bool] = Field(
default=False,
description="Plan the crew execution and add the plan to the crew.",
)
@field_validator("id", mode="before")
@classmethod
@@ -340,6 +345,9 @@ class Crew(BaseModel):
agent.create_agent_executor()
if self.planning:
self._handle_crew_planning()
metrics = []
if self.process == Process.sequential:
@@ -421,6 +429,14 @@ class Crew(BaseModel):
return results
def _handle_crew_planning(self):
"""Handles the Crew planning."""
self._logger.log("info", "Planning the crew execution")
result = CrewPlanner(self.tasks)._handle_crew_planning()
for task, step_plan in zip(self.tasks, result.list_of_plans_per_task):
task.description += step_plan
def _run_sequential_process(self) -> Union[str, Dict[str, Any]]:
"""Executes tasks sequentially and returns the final output."""
task_output = None

View File

@@ -13,8 +13,7 @@ from pydantic_core import PydanticCustomError
from crewai.agents.agent_builder.base_agent import BaseAgent
from crewai.tasks.task_output import TaskOutput
from crewai.telemetry.telemetry import Telemetry
from crewai.utilities.converter import ConverterError
from crewai.utilities.converter import Converter
from crewai.utilities.converter import Converter, ConverterError
from crewai.utilities.i18n import I18N
from crewai.utilities.printer import Printer
from crewai.utilities.pydantic_schema_parser import PydanticSchemaParser
@@ -179,15 +178,13 @@ class Task(BaseModel):
agent: BaseAgent | None = None,
context: Optional[str] = None,
tools: Optional[List[Any]] = None,
) -> str | None:
) -> Any:
"""Execute the task.
Returns:
Output of the task.
"""
self._execution_span = self._telemetry.task_started(self)
agent = agent or self.agent
if not agent:
raise Exception(
@@ -195,6 +192,8 @@ class Task(BaseModel):
"and should be executed in a Crew using a specific process that support that, like hierarchical."
)
self._execution_span = self._telemetry.task_started(crew=agent.crew, task=self)
if self.context:
internal_context = []
for task in self.context:
@@ -292,7 +291,7 @@ class Task(BaseModel):
copied_data = {k: v for k, v in copied_data.items() if v is not None}
cloned_context = (
[task.copy() for task in self.context] if self.context else None
[task.copy(agents) for task in self.context] if self.context else None
)
def get_agent_by_role(role: str) -> Union["BaseAgent", None]:
@@ -310,17 +309,17 @@ class Task(BaseModel):
return copied_task
def _create_converter(self, *args, **kwargs) -> Converter: # type: ignore
converter = self.agent.get_output_converter( # type: ignore # Item "None" of "BaseAgent | None" has no attribute "get_output_converter"
*args, **kwargs
)
if self.converter_cls:
converter = self.converter_cls( # type: ignore # Item "None" of "BaseAgent | None" has no attribute "get_output_converter"
*args, **kwargs
)
return converter
def _create_converter(self, *args, **kwargs) -> Converter: # type: ignore
converter = self.agent.get_output_converter( # type: ignore # Item "None" of "BaseAgent | None" has no attribute "get_output_converter"
*args, **kwargs
)
if self.converter_cls:
converter = self.converter_cls( # type: ignore # Item "None" of "BaseAgent | None" has no attribute "get_output_converter"
*args, **kwargs
)
return converter
def _export_output(self, result: str) -> Any:
def _export_output(self, result: str) -> Any: # TODO: Refactor and fix type hints
exported_result = result
instructions = "I'm gonna convert this raw text into valid JSON."
@@ -350,7 +349,7 @@ class Task(BaseModel):
model_schema = PydanticSchemaParser(model=model).get_schema() # type: ignore # Argument "model" to "PydanticSchemaParser" has incompatible type "type[BaseModel] | None"; expected "type[BaseModel]"
instructions = f"{instructions}\n\nThe json should have the following structure, with the following keys:\n{model_schema}"
converter = self._create_converter( # type: ignore # Item "None" of "BaseAgent | None" has no attribute "get_output_converter"
converter = self._create_converter( # type: ignore # Item "None" of "BaseAgent | None" has no attribute "get_output_converter"
llm=llm, text=result, model=model, instructions=instructions
)

View File

@@ -156,18 +156,35 @@ class Telemetry:
except Exception:
pass
def task_started(self, task: Task) -> Span | None:
def task_started(self, crew: Crew, task: Task) -> Span | None:
"""Records task started in a crew."""
if self.ready:
try:
tracer = trace.get_tracer("crewai.telemetry")
span = tracer.start_span("Task Execution")
created_span = tracer.start_span("Task Created")
self._add_attribute(created_span, "task_id", str(task.id))
if crew.share_crew:
self._add_attribute(
created_span, "formatted_description", task.description
)
self._add_attribute(
created_span, "formatted_expected_output", task.expected_output
)
created_span.set_status(Status(StatusCode.OK))
created_span.end()
self._add_attribute(span, "task_id", str(task.id))
self._add_attribute(span, "formatted_description", task.description)
self._add_attribute(
span, "formatted_expected_output", task.expected_output
)
if crew.share_crew:
self._add_attribute(span, "formatted_description", task.description)
self._add_attribute(
span, "formatted_expected_output", task.expected_output
)
return span
except Exception:

View File

@@ -8,7 +8,7 @@ from pydantic.v1 import BaseModel, Field
class ToolCalling(BaseModel):
tool_name: str = Field(..., description="The name of the tool to be called.")
arguments: Optional[Dict[str, Any]] = Field(
..., description="A dictinary of arguments to be passed to the tool."
..., description="A dictionary of arguments to be passed to the tool."
)
@@ -17,5 +17,5 @@ class InstructorToolCalling(PydanticBaseModel):
..., description="The name of the tool to be called."
)
arguments: Optional[Dict[str, Any]] = PydanticField(
..., description="A dictinary of arguments to be passed to the tool."
..., description="A dictionary of arguments to be passed to the tool."
)

View File

@@ -119,7 +119,7 @@ class ToolUsage:
attempts=self._run_attempts,
)
result = self._format_result(result=result) # type: ignore # "_format_result" of "ToolUsage" does not return a value (it only ever returns None)
return result # type: ignore # Fix the reutrn type of this function
return result # type: ignore # Fix the return type of this function
except Exception:
self.task.increment_tools_errors()

View File

@@ -16,7 +16,7 @@
"format_without_tools": "\nSorry, I didn't use the right format. I MUST either use a tool (among the available ones), OR give my best final answer.\nI just remembered the expected format I must follow:\n\nQuestion: the input question you must answer\nThought: you should always think about what to do\nAction: the action to take, should be one of [{tool_names}]\nAction Input: the input to the action\nObservation: the result of the action\n... (this Thought/Action/Action Input/Observation can repeat N times)\nThought: I now can give a great answer\nFinal Answer: my best complete final answer to the task\nYour final answer must be the great and the most complete as possible, it must be outcome described\n\n",
"task_with_context": "{task}\n\nThis is the context you're working with:\n{context}",
"expected_output": "\nThis is the expect criteria for your final answer: {expected_output} \n you MUST return the actual complete content as the final answer, not a summary.",
"human_feedback": "You got human feedback on your work, re-avaluate it and give a new Final Answer when ready.\n {human_feedback}",
"human_feedback": "You got human feedback on your work, re-evaluate it and give a new Final Answer when ready.\n {human_feedback}",
"getting_input": "This is the agent's final answer: {final_answer}\nPlease provide feedback: "
},
"errors": {

View File

@@ -0,0 +1,64 @@
from typing import List
from pydantic import BaseModel
from crewai.agent import Agent
from crewai.task import Task
class PlannerTaskPydanticOutput(BaseModel):
list_of_plans_per_task: List[str]
class CrewPlanner:
def __init__(self, tasks: List[Task]):
self.tasks = tasks
def _handle_crew_planning(self):
"""Handles the Crew planning by creating detailed step-by-step plans for each task."""
planning_agent = self._create_planning_agent()
tasks_summary = self._create_tasks_summary()
planner_task = self._create_planner_task(planning_agent, tasks_summary)
return planner_task.execute()
def _create_planning_agent(self) -> Agent:
"""Creates the planning agent for the crew planning."""
return Agent(
role="Task Execution Planner",
goal=(
"Your goal is to create an extremely detailed, step-by-step plan based on the tasks and tools "
"available to each agent so that they can perform the tasks in an exemplary manner"
),
backstory="Planner agent for crew planning",
)
def _create_planner_task(self, planning_agent: Agent, tasks_summary: str) -> Task:
"""Creates the planner task using the given agent and tasks summary."""
return Task(
description=(
f"Based on these tasks summary: {tasks_summary} \n Create the most descriptive plan based on the tasks "
"descriptions, tools available, and agents' goals for them to execute their goals with perfection."
),
expected_output="Step by step plan on how the agents can execute their tasks using the available tools with mastery",
agent=planning_agent,
output_pydantic=PlannerTaskPydanticOutput,
)
def _create_tasks_summary(self) -> str:
"""Creates a summary of all tasks."""
tasks_summary = []
for idx, task in enumerate(self.tasks):
tasks_summary.append(
f"""
Task Number {idx + 1} - {task.description}
"task_description": {task.description}
"task_expected_output": {task.expected_output}
"agent": {task.agent.role if task.agent else "None"}
"agent_goal": {task.agent.goal if task.agent else "None"}
"task_tools": {task.tools}
"agent_tools": {task.agent.tools if task.agent else "None"}
"""
)
return " ".join(tasks_summary)