11import shutil
22import subprocess
33import time
4+ from collections .abc import Callable , Sequence
45from typing import (
56 Any ,
6- Callable ,
7- Dict ,
8- List ,
97 Literal ,
10- Optional ,
11- Sequence ,
12- Tuple ,
13- Type ,
14- Union ,
158)
169
1710from pydantic import Field , InstanceOf , PrivateAttr , model_validator
1811
1912from crewai .agents import CacheHandler
2013from crewai .agents .agent_builder .base_agent import BaseAgent
2114from crewai .agents .crew_agent_executor import CrewAgentExecutor
15+ from crewai .events .event_bus import crewai_event_bus
16+ from crewai .events .types .agent_events import (
17+ AgentExecutionCompletedEvent ,
18+ AgentExecutionErrorEvent ,
19+ AgentExecutionStartedEvent ,
20+ )
21+ from crewai .events .types .knowledge_events import (
22+ KnowledgeQueryCompletedEvent ,
23+ KnowledgeQueryFailedEvent ,
24+ KnowledgeQueryStartedEvent ,
25+ KnowledgeRetrievalCompletedEvent ,
26+ KnowledgeRetrievalStartedEvent ,
27+ KnowledgeSearchQueryFailedEvent ,
28+ )
29+ from crewai .events .types .memory_events import (
30+ MemoryRetrievalCompletedEvent ,
31+ MemoryRetrievalStartedEvent ,
32+ )
2233from crewai .knowledge .knowledge import Knowledge
2334from crewai .knowledge .source .base_knowledge_source import BaseKnowledgeSource
2435from crewai .knowledge .utils .knowledge_utils import extract_knowledge_context
2536from crewai .lite_agent import LiteAgent , LiteAgentOutput
2637from crewai .llm import BaseLLM
2738from crewai .memory .contextual .contextual_memory import ContextualMemory
39+ from crewai .rag .embeddings .types import EmbedderConfig
2840from crewai .security import Fingerprint
2941from crewai .task import Task
3042from crewai .tools import BaseTool
3850)
3951from crewai .utilities .constants import TRAINED_AGENTS_DATA_FILE , TRAINING_DATA_FILE
4052from crewai .utilities .converter import generate_model_description
41- from crewai .events .types .agent_events import (
42- AgentExecutionCompletedEvent ,
43- AgentExecutionErrorEvent ,
44- AgentExecutionStartedEvent ,
45- )
46- from crewai .events .event_bus import crewai_event_bus
47- from crewai .events .types .memory_events import (
48- MemoryRetrievalStartedEvent ,
49- MemoryRetrievalCompletedEvent ,
50- )
51- from crewai .events .types .knowledge_events import (
52- KnowledgeQueryCompletedEvent ,
53- KnowledgeQueryFailedEvent ,
54- KnowledgeQueryStartedEvent ,
55- KnowledgeRetrievalCompletedEvent ,
56- KnowledgeRetrievalStartedEvent ,
57- KnowledgeSearchQueryFailedEvent ,
58- )
5953from crewai .utilities .llm_utils import create_llm
6054from crewai .utilities .token_counter_callback import TokenCalcHandler
6155from crewai .utilities .training_handler import CrewTrainingHandler
@@ -87,36 +81,36 @@ class Agent(BaseAgent):
8781 """
8882
8983 _times_executed : int = PrivateAttr (default = 0 )
90- max_execution_time : Optional [ int ] = Field (
84+ max_execution_time : int | None = Field (
9185 default = None ,
9286 description = "Maximum execution time for an agent to execute a task" ,
9387 )
9488 agent_ops_agent_name : str = None # type: ignore # Incompatible types in assignment (expression has type "None", variable has type "str")
9589 agent_ops_agent_id : str = None # type: ignore # Incompatible types in assignment (expression has type "None", variable has type "str")
96- step_callback : Optional [ Any ] = Field (
90+ step_callback : Any | None = Field (
9791 default = None ,
9892 description = "Callback to be executed after each step of the agent execution." ,
9993 )
100- use_system_prompt : Optional [ bool ] = Field (
94+ use_system_prompt : bool | None = Field (
10195 default = True ,
10296 description = "Use system prompt for the agent." ,
10397 )
104- llm : Union [ str , InstanceOf [BaseLLM ], Any ] = Field (
98+ llm : str | InstanceOf [BaseLLM ] | Any = Field (
10599 description = "Language model that will run the agent." , default = None
106100 )
107- function_calling_llm : Optional [ Union [ str , InstanceOf [BaseLLM ], Any ]] = Field (
101+ function_calling_llm : str | InstanceOf [BaseLLM ] | Any | None = Field (
108102 description = "Language model that will run the agent." , default = None
109103 )
110- system_template : Optional [ str ] = Field (
104+ system_template : str | None = Field (
111105 default = None , description = "System format for the agent."
112106 )
113- prompt_template : Optional [ str ] = Field (
107+ prompt_template : str | None = Field (
114108 default = None , description = "Prompt format for the agent."
115109 )
116- response_template : Optional [ str ] = Field (
110+ response_template : str | None = Field (
117111 default = None , description = "Response format for the agent."
118112 )
119- allow_code_execution : Optional [ bool ] = Field (
113+ allow_code_execution : bool | None = Field (
120114 default = False , description = "Enable code execution for the agent."
121115 )
122116 respect_context_window : bool = Field (
@@ -147,31 +141,31 @@ class Agent(BaseAgent):
147141 default = False ,
148142 description = "Whether the agent should reflect and create a plan before executing a task." ,
149143 )
150- max_reasoning_attempts : Optional [ int ] = Field (
144+ max_reasoning_attempts : int | None = Field (
151145 default = None ,
152146 description = "Maximum number of reasoning attempts before executing the task. If None, will try until ready." ,
153147 )
154- embedder : Optional [ Dict [ str , Any ]] = Field (
148+ embedder : EmbedderConfig | None = Field (
155149 default = None ,
156150 description = "Embedder configuration for the agent." ,
157151 )
158- agent_knowledge_context : Optional [ str ] = Field (
152+ agent_knowledge_context : str | None = Field (
159153 default = None ,
160154 description = "Knowledge context for the agent." ,
161155 )
162- crew_knowledge_context : Optional [ str ] = Field (
156+ crew_knowledge_context : str | None = Field (
163157 default = None ,
164158 description = "Knowledge context for the crew." ,
165159 )
166- knowledge_search_query : Optional [ str ] = Field (
160+ knowledge_search_query : str | None = Field (
167161 default = None ,
168162 description = "Knowledge search query for the agent dynamically generated by the agent." ,
169163 )
170- from_repository : Optional [ str ] = Field (
164+ from_repository : str | None = Field (
171165 default = None ,
172166 description = "The Agent's role to be used from your repository." ,
173167 )
174- guardrail : Optional [ Union [ Callable [[Any ], Tuple [bool , Any ]], str ]] = Field (
168+ guardrail : Callable [[Any ], tuple [bool , Any ]] | str | None = Field (
175169 default = None ,
176170 description = "Function or string description of a guardrail to validate agent output" ,
177171 )
@@ -180,7 +174,7 @@ class Agent(BaseAgent):
180174 )
181175
182176 @model_validator (mode = "before" )
183- def validate_from_repository (cls , v ):
177+ def validate_from_repository (cls , v ): # noqa: N805
184178 if v is not None and (from_repository := v .get ("from_repository" )):
185179 return load_agent_from_repository (from_repository ) | v
186180 return v
@@ -208,7 +202,7 @@ def _setup_agent_executor(self):
208202 self .cache_handler = CacheHandler ()
209203 self .set_cache_handler (self .cache_handler )
210204
211- def set_knowledge (self , crew_embedder : Optional [ Dict [ str , Any ]] = None ):
205+ def set_knowledge (self , crew_embedder : EmbedderConfig | None = None ):
212206 try :
213207 if self .embedder is None and crew_embedder :
214208 self .embedder = crew_embedder
@@ -224,7 +218,7 @@ def set_knowledge(self, crew_embedder: Optional[Dict[str, Any]] = None):
224218 )
225219 self .knowledge .add_sources ()
226220 except (TypeError , ValueError ) as e :
227- raise ValueError (f"Invalid Knowledge Configuration: { str ( e ) } " )
221+ raise ValueError (f"Invalid Knowledge Configuration: { e !s } " ) from e
228222
229223 def _is_any_available_memory (self ) -> bool :
230224 """Check if any memory is available."""
@@ -244,8 +238,8 @@ def _is_any_available_memory(self) -> bool:
244238 def execute_task (
245239 self ,
246240 task : Task ,
247- context : Optional [ str ] = None ,
248- tools : Optional [ List [ BaseTool ]] = None ,
241+ context : str | None = None ,
242+ tools : list [ BaseTool ] | None = None ,
249243 ) -> str :
250244 """Execute a task with the agent.
251245
@@ -278,11 +272,9 @@ def execute_task(
278272 task .description += f"\n \n Reasoning Plan:\n { reasoning_output .plan .plan } "
279273 except Exception as e :
280274 if hasattr (self , "_logger" ):
281- self ._logger .log (
282- "error" , f"Error during reasoning process: { str (e )} "
283- )
275+ self ._logger .log ("error" , f"Error during reasoning process: { e !s} " )
284276 else :
285- print (f"Error during reasoning process: { str ( e ) } " )
277+ print (f"Error during reasoning process: { e !s } " )
286278
287279 self ._inject_date_to_task (task )
288280
@@ -335,7 +327,7 @@ def execute_task(
335327 agent = self ,
336328 task = task ,
337329 )
338- memory = contextual_memory .build_context_for_task (task , context )
330+ memory = contextual_memory .build_context_for_task (task , context ) # type: ignore[arg-type]
339331 if memory .strip () != "" :
340332 task_prompt += self .i18n .slice ("memory" ).format (memory = memory )
341333
@@ -525,14 +517,14 @@ def _execute_with_timeout(self, task_prompt: str, task: Task, timeout: int) -> s
525517
526518 try :
527519 return future .result (timeout = timeout )
528- except concurrent .futures .TimeoutError :
520+ except concurrent .futures .TimeoutError as e :
529521 future .cancel ()
530522 raise TimeoutError (
531523 f"Task '{ task .description } ' execution timed out after { timeout } seconds. Consider increasing max_execution_time or optimizing the task."
532- )
524+ ) from e
533525 except Exception as e :
534526 future .cancel ()
535- raise RuntimeError (f"Task execution failed: { str ( e ) } " )
527+ raise RuntimeError (f"Task execution failed: { e !s } " ) from e
536528
537529 def _execute_without_timeout (self , task_prompt : str , task : Task ) -> str :
538530 """Execute a task without a timeout.
@@ -554,14 +546,14 @@ def _execute_without_timeout(self, task_prompt: str, task: Task) -> str:
554546 )["output" ]
555547
556548 def create_agent_executor (
557- self , tools : Optional [ List [ BaseTool ]] = None , task = None
549+ self , tools : list [ BaseTool ] | None = None , task = None
558550 ) -> None :
559551 """Create an agent executor for the agent.
560552
561553 Returns:
562554 An instance of the CrewAgentExecutor class.
563555 """
564- raw_tools : List [BaseTool ] = tools or self .tools or []
556+ raw_tools : list [BaseTool ] = tools or self .tools or []
565557 parsed_tools = parse_tools (raw_tools )
566558
567559 prompt = Prompts (
@@ -587,7 +579,7 @@ def create_agent_executor(
587579 agent = self ,
588580 crew = self .crew ,
589581 tools = parsed_tools ,
590- prompt = prompt ,
582+ prompt = prompt , # type: ignore[arg-type]
591583 original_tools = raw_tools ,
592584 stop_words = stop_words ,
593585 max_iter = self .max_iter ,
@@ -603,10 +595,9 @@ def create_agent_executor(
603595 callbacks = [TokenCalcHandler (self ._token_process )],
604596 )
605597
606- def get_delegation_tools (self , agents : List [BaseAgent ]):
598+ def get_delegation_tools (self , agents : list [BaseAgent ]):
607599 agent_tools = AgentTools (agents = agents )
608- tools = agent_tools .tools ()
609- return tools
600+ return agent_tools .tools ()
610601
611602 def get_multimodal_tools (self ) -> Sequence [BaseTool ]:
612603 from crewai .tools .agent_tools .add_image_tool import AddImageTool
@@ -654,7 +645,7 @@ def _use_trained_data(self, task_prompt: str) -> str:
654645 )
655646 return task_prompt
656647
657- def _render_text_description (self , tools : List [Any ]) -> str :
648+ def _render_text_description (self , tools : list [Any ]) -> str :
658649 """Render the tool name and description in plain text.
659650
660651 Output will be in the format of:
@@ -664,15 +655,13 @@ def _render_text_description(self, tools: List[Any]) -> str:
664655 search: This tool is used for search
665656 calculator: This tool is used for math
666657 """
667- description = "\n " .join (
658+ return "\n " .join (
668659 [
669660 f"Tool name: { tool .name } \n Tool description:\n { tool .description } "
670661 for tool in tools
671662 ]
672663 )
673664
674- return description
675-
676665 def _inject_date_to_task (self , task ):
677666 """Inject the current date into the task description if inject_date is enabled."""
678667 if self .inject_date :
@@ -696,13 +685,13 @@ def _inject_date_to_task(self, task):
696685 if not is_valid :
697686 raise ValueError (f"Invalid date format: { self .date_format } " )
698687
699- current_date : str = datetime .now ().strftime (self .date_format )
688+ current_date = datetime .now ().strftime (self .date_format )
700689 task .description += f"\n \n Current Date: { current_date } "
701690 except Exception as e :
702691 if hasattr (self , "_logger" ):
703- self ._logger .log ("warning" , f"Failed to inject date: { str ( e ) } " )
692+ self ._logger .log ("warning" , f"Failed to inject date: { e !s } " )
704693 else :
705- print (f"Warning: Failed to inject date: { str ( e ) } " )
694+ print (f"Warning: Failed to inject date: { e !s } " )
706695
707696 def _validate_docker_installation (self ) -> None :
708697 """Check if Docker is installed and running."""
@@ -713,15 +702,15 @@ def _validate_docker_installation(self) -> None:
713702
714703 try :
715704 subprocess .run (
716- ["docker" , "info" ],
705+ ["/usr/bin/ docker" , "info" ],
717706 check = True ,
718707 stdout = subprocess .PIPE ,
719708 stderr = subprocess .PIPE ,
720709 )
721- except subprocess .CalledProcessError :
710+ except subprocess .CalledProcessError as e :
722711 raise RuntimeError (
723712 f"Docker is not running. Please start Docker to use code execution with agent: { self .role } "
724- )
713+ ) from e
725714
726715 def __repr__ (self ):
727716 return f"Agent(role={ self .role } , goal={ self .goal } , backstory={ self .backstory } )"
@@ -796,8 +785,8 @@ def _get_knowledge_search_query(self, task_prompt: str) -> str | None:
796785
797786 def kickoff (
798787 self ,
799- messages : Union [ str , List [ Dict [str , str ] ]],
800- response_format : Optional [ Type [ Any ]] = None ,
788+ messages : str | list [ dict [str , str ]],
789+ response_format : type [ Any ] | None = None ,
801790 ) -> LiteAgentOutput :
802791 """
803792 Execute the agent with the given messages using a LiteAgent instance.
@@ -836,8 +825,8 @@ def kickoff(
836825
837826 async def kickoff_async (
838827 self ,
839- messages : Union [ str , List [ Dict [str , str ] ]],
840- response_format : Optional [ Type [ Any ]] = None ,
828+ messages : str | list [ dict [str , str ]],
829+ response_format : type [ Any ] | None = None ,
841830 ) -> LiteAgentOutput :
842831 """
843832 Execute the agent asynchronously with the given messages using a LiteAgent instance.
0 commit comments