From bc91e94f039d75cb74eccc9e0e8e3b6d65b60bae Mon Sep 17 00:00:00 2001 From: Lucas Gomide Date: Mon, 14 Apr 2025 17:58:09 -0300 Subject: [PATCH] fix: add type hints and ignore type checks for config access (#2603) --- README.md | 4 +++ docs/concepts/agents.mdx | 4 +-- docs/concepts/crews.mdx | 14 +++++---- docs/concepts/llms.mdx | 2 +- docs/concepts/tasks.mdx | 8 ++--- docs/guides/crews/first-crew.mdx | 15 ++++++---- docs/guides/flows/first-flow.mdx | 13 +++++--- docs/quickstart.mdx | 13 +++++--- src/crewai/cli/templates/crew/crew.py | 18 ++++++----- .../flow/crews/poem_crew/poem_crew.py | 9 ++++-- tests/crew_test.py | 10 +++++-- tests/project_test.py | 30 ++++++++++++------- 12 files changed, 93 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index a1bf63645..4d563daee 100644 --- a/README.md +++ b/README.md @@ -257,10 +257,14 @@ reporting_task: from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task from crewai_tools import SerperDevTool +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List @CrewBase class LatestAiDevelopmentCrew(): """LatestAiDevelopment crew""" + agents: List[BaseAgent] + tasks: List[Task] @agent def researcher(self) -> Agent: diff --git a/docs/concepts/agents.mdx b/docs/concepts/agents.mdx index 8f04b9d49..fa954d4fc 100644 --- a/docs/concepts/agents.mdx +++ b/docs/concepts/agents.mdx @@ -118,7 +118,7 @@ class LatestAiDevelopmentCrew(): @agent def researcher(self) -> Agent: return Agent( - config=self.agents_config['researcher'], + config=self.agents_config['researcher'], # type: ignore[index] verbose=True, tools=[SerperDevTool()] ) @@ -126,7 +126,7 @@ class LatestAiDevelopmentCrew(): @agent def reporting_analyst(self) -> Agent: return Agent( - config=self.agents_config['reporting_analyst'], + config=self.agents_config['reporting_analyst'], # type: ignore[index] verbose=True ) ``` diff --git a/docs/concepts/crews.mdx b/docs/concepts/crews.mdx index e5602539a..76268457e 100644 --- a/docs/concepts/crews.mdx +++ b/docs/concepts/crews.mdx @@ -52,12 +52,16 @@ After creating your CrewAI project as outlined in the [Installation](/installati ```python code from crewai import Agent, Crew, Task, Process from crewai.project import CrewBase, agent, task, crew, before_kickoff, after_kickoff - +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List @CrewBase class YourCrewName: """Description of your crew""" + agents: List[BaseAgent] + tasks: List[Task] + # 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 @@ -80,27 +84,27 @@ class YourCrewName: @agent def agent_one(self) -> Agent: return Agent( - config=self.agents_config['agent_one'], + config=self.agents_config['agent_one'], # type: ignore[index] verbose=True ) @agent def agent_two(self) -> Agent: return Agent( - config=self.agents_config['agent_two'], + config=self.agents_config['agent_two'], # type: ignore[index] verbose=True ) @task def task_one(self) -> Task: return Task( - config=self.tasks_config['task_one'] + config=self.tasks_config['task_one'] # type: ignore[index] ) @task def task_two(self) -> Task: return Task( - config=self.tasks_config['task_two'] + config=self.tasks_config['task_two'] # type: ignore[index] ) @crew diff --git a/docs/concepts/llms.mdx b/docs/concepts/llms.mdx index f2f027746..560448f21 100644 --- a/docs/concepts/llms.mdx +++ b/docs/concepts/llms.mdx @@ -438,7 +438,7 @@ In this section, you'll find detailed examples that help you select, configure, @agent def researcher(self) -> Agent: return Agent( - config=self.agents_config['researcher'], + config=self.agents_config['researcher'], # type: ignore[index] llm=local_nvidia_nim_llm ) diff --git a/docs/concepts/tasks.mdx b/docs/concepts/tasks.mdx index 8a0ce74e0..2a47448de 100644 --- a/docs/concepts/tasks.mdx +++ b/docs/concepts/tasks.mdx @@ -113,7 +113,7 @@ class LatestAiDevelopmentCrew(): @agent def researcher(self) -> Agent: return Agent( - config=self.agents_config['researcher'], + config=self.agents_config['researcher'], # type: ignore[index] verbose=True, tools=[SerperDevTool()] ) @@ -121,20 +121,20 @@ class LatestAiDevelopmentCrew(): @agent def reporting_analyst(self) -> Agent: return Agent( - config=self.agents_config['reporting_analyst'], + config=self.agents_config['reporting_analyst'], # type: ignore[index] verbose=True ) @task def research_task(self) -> Task: return Task( - config=self.tasks_config['research_task'] + config=self.tasks_config['research_task'] # type: ignore[index] ) @task def reporting_task(self) -> Task: return Task( - config=self.tasks_config['reporting_task'] + config=self.tasks_config['reporting_task'] # type: ignore[index] ) @crew diff --git a/docs/guides/crews/first-crew.mdx b/docs/guides/crews/first-crew.mdx index 8aa384112..8eb2619d1 100644 --- a/docs/guides/crews/first-crew.mdx +++ b/docs/guides/crews/first-crew.mdx @@ -185,15 +185,20 @@ Let's modify the `crew.py` file: from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task from crewai_tools import SerperDevTool +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List @CrewBase class ResearchCrew(): """Research crew for comprehensive topic analysis and reporting""" + agents: List[BaseAgent] + tasks: List[Task] + @agent def researcher(self) -> Agent: return Agent( - config=self.agents_config['researcher'], + config=self.agents_config['researcher'], # type: ignore[index] verbose=True, tools=[SerperDevTool()] ) @@ -201,20 +206,20 @@ class ResearchCrew(): @agent def analyst(self) -> Agent: return Agent( - config=self.agents_config['analyst'], + config=self.agents_config['analyst'], # type: ignore[index] verbose=True ) @task def research_task(self) -> Task: return Task( - config=self.tasks_config['research_task'] + config=self.tasks_config['research_task'] # type: ignore[index] ) @task def analysis_task(self) -> Task: return Task( - config=self.tasks_config['analysis_task'], + config=self.tasks_config['analysis_task'], # type: ignore[index] output_file='output/report.md' ) @@ -387,4 +392,4 @@ Now that you've built your first crew, you can: Congratulations! You've successfully built your first CrewAI crew that can research and analyze any topic you provide. This foundational experience has equipped you with the skills to create increasingly sophisticated AI systems that can tackle complex, multi-stage problems through collaborative intelligence. - \ No newline at end of file + diff --git a/docs/guides/flows/first-flow.mdx b/docs/guides/flows/first-flow.mdx index cb10de275..d5784f0a9 100644 --- a/docs/guides/flows/first-flow.mdx +++ b/docs/guides/flows/first-flow.mdx @@ -203,35 +203,40 @@ These task definitions provide detailed instructions to our agents, ensuring the # 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 +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List @CrewBase class ContentCrew(): """Content writing crew""" + agents: List[BaseAgent] + tasks: List[Task] + @agent def content_writer(self) -> Agent: return Agent( - config=self.agents_config['content_writer'], + config=self.agents_config['content_writer'], # type: ignore[index] verbose=True ) @agent def content_reviewer(self) -> Agent: return Agent( - config=self.agents_config['content_reviewer'], + config=self.agents_config['content_reviewer'], # type: ignore[index] verbose=True ) @task def write_section_task(self) -> Task: return Task( - config=self.tasks_config['write_section_task'] + config=self.tasks_config['write_section_task'] # type: ignore[index] ) @task def review_section_task(self) -> Task: return Task( - config=self.tasks_config['review_section_task'], + config=self.tasks_config['review_section_task'], # type: ignore[index] context=[self.write_section_task()] ) diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx index 2cbc2df9a..cb01c15cc 100644 --- a/docs/quickstart.mdx +++ b/docs/quickstart.mdx @@ -87,15 +87,20 @@ Follow the steps below to get Crewing! 🚣‍♂️ from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task from crewai_tools import SerperDevTool + from crewai.agents.agent_builder.base_agent import BaseAgent + from typing import List @CrewBase class LatestAiDevelopmentCrew(): """LatestAiDevelopment crew""" + agents: List[BaseAgent] + tasks: List[Task] + @agent def researcher(self) -> Agent: return Agent( - config=self.agents_config['researcher'], + config=self.agents_config['researcher'], # type: ignore[index] verbose=True, tools=[SerperDevTool()] ) @@ -103,20 +108,20 @@ Follow the steps below to get Crewing! 🚣‍♂️ @agent def reporting_analyst(self) -> Agent: return Agent( - config=self.agents_config['reporting_analyst'], + config=self.agents_config['reporting_analyst'], # type: ignore[index] verbose=True ) @task def research_task(self) -> Task: return Task( - config=self.tasks_config['research_task'], + config=self.tasks_config['research_task'], # type: ignore[index] ) @task def reporting_task(self) -> Task: return Task( - config=self.tasks_config['reporting_task'], + config=self.tasks_config['reporting_task'], # type: ignore[index] output_file='output/report.md' # This is the file that will be contain the final report. ) diff --git a/src/crewai/cli/templates/crew/crew.py b/src/crewai/cli/templates/crew/crew.py index 700f97c07..43a2608a4 100644 --- a/src/crewai/cli/templates/crew/crew.py +++ b/src/crewai/cli/templates/crew/crew.py @@ -1,6 +1,7 @@ from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task - +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List # 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 @@ -9,25 +10,26 @@ from crewai.project import CrewBase, agent, crew, task class {{crew_name}}(): """{{crew_name}} crew""" + agents: List[BaseAgent] + tasks: List[Task] + # 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' - + # 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'], + config=self.agents_config['researcher'], # type: ignore[index] verbose=True ) @agent def reporting_analyst(self) -> Agent: return Agent( - config=self.agents_config['reporting_analyst'], + config=self.agents_config['reporting_analyst'], # type: ignore[index] verbose=True ) @@ -37,13 +39,13 @@ class {{crew_name}}(): @task def research_task(self) -> Task: return Task( - config=self.tasks_config['research_task'], + config=self.tasks_config['research_task'], # type: ignore[index] ) @task def reporting_task(self) -> Task: return Task( - config=self.tasks_config['reporting_task'], + config=self.tasks_config['reporting_task'], # type: ignore[index] output_file='report.md' ) 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 5e978d985..1f2a81466 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,5 +1,7 @@ from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List # 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 @@ -10,6 +12,9 @@ from crewai.project import CrewBase, agent, crew, task class PoemCrew: """Poem Crew""" + agents: List[BaseAgent] + tasks: List[Task] + # 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 @@ -21,7 +26,7 @@ class PoemCrew: @agent def poem_writer(self) -> Agent: return Agent( - config=self.agents_config["poem_writer"], + config=self.agents_config["poem_writer"], # type: ignore[index] ) # To learn more about structured task outputs, @@ -30,7 +35,7 @@ class PoemCrew: @task def write_poem(self) -> Task: return Task( - config=self.tasks_config["write_poem"], + config=self.tasks_config["write_poem"], # type: ignore[index] ) @crew diff --git a/tests/crew_test.py b/tests/crew_test.py index c2ffe7350..fd0d9f3d4 100644 --- a/tests/crew_test.py +++ b/tests/crew_test.py @@ -4069,11 +4069,17 @@ def test_crew_guardrail_feedback_in_context(): @pytest.mark.vcr(filter_headers=["authorization"]) def test_before_kickoff_callback(): - from crewai.project import CrewBase, agent, before_kickoff, task + from crewai.project import CrewBase @CrewBase class TestCrewClass: - from crewai.project import crew + from typing import List + + from crewai.agents.agent_builder.base_agent import BaseAgent + from crewai.project import CrewBase, agent, before_kickoff, crew, task + + agents: List[BaseAgent] + tasks: List[Task] agents_config = None tasks_config = None diff --git a/tests/project_test.py b/tests/project_test.py index e0813a13f..c07922351 100644 --- a/tests/project_test.py +++ b/tests/project_test.py @@ -1,6 +1,9 @@ +from typing import List + import pytest from crewai.agent import Agent +from crewai.agents.agent_builder.base_agent import BaseAgent from crewai.crew import Crew from crewai.llm import LLM from crewai.project import ( @@ -40,28 +43,32 @@ class InternalCrew: agents_config = "config/agents.yaml" tasks_config = "config/tasks.yaml" + agents: List[BaseAgent] + tasks: List[Task] + @llm def local_llm(self): return LLM( - model='openai/model_name', + model="openai/model_name", api_key="None", - base_url="http://xxx.xxx.xxx.xxx:8000/v1") + base_url="http://xxx.xxx.xxx.xxx:8000/v1", + ) @agent def researcher(self): - return Agent(config=self.agents_config["researcher"]) + return Agent(config=self.agents_config["researcher"]) # type: ignore[index] @agent def reporting_analyst(self): - return Agent(config=self.agents_config["reporting_analyst"]) + return Agent(config=self.agents_config["reporting_analyst"]) # type: ignore[index] @task def research_task(self): - return Task(config=self.tasks_config["research_task"]) + return Task(config=self.tasks_config["research_task"]) # type: ignore[index] @task def reporting_task(self): - return Task(config=self.tasks_config["reporting_task"]) + return Task(config=self.tasks_config["reporting_task"]) # type: ignore[index] @before_kickoff def modify_inputs(self, inputs): @@ -165,24 +172,27 @@ def test_before_kickoff_with_none_input(): def test_multiple_before_after_kickoff(): @CrewBase class MultipleHooksCrew: + agents: List[BaseAgent] + tasks: List[Task] + agents_config = "config/agents.yaml" tasks_config = "config/tasks.yaml" @agent def researcher(self): - return Agent(config=self.agents_config["researcher"]) + return Agent(config=self.agents_config["researcher"]) # type: ignore[index] @agent def reporting_analyst(self): - return Agent(config=self.agents_config["reporting_analyst"]) + return Agent(config=self.agents_config["reporting_analyst"]) # type: ignore[index] @task def research_task(self): - return Task(config=self.tasks_config["research_task"]) + return Task(config=self.tasks_config["research_task"]) # type: ignore[index] @task def reporting_task(self): - return Task(config=self.tasks_config["reporting_task"]) + return Task(config=self.tasks_config["reporting_task"]) # type: ignore[index] @before_kickoff def first_before(self, inputs):