From e1a73e0c44fd85b2ad34ca0a3eda57964c0dee4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moura?= Date: Wed, 26 Mar 2025 14:54:23 -0700 Subject: [PATCH] Using fingerprints (#2456) * using fingerprints * passing fingerptins on tools * fix * update lock * Fix type checker errors --------- Co-authored-by: Brandon Hancock Co-authored-by: Brandon Hancock (bhancock_ai) <109994880+bhancockio@users.noreply.github.com> Co-authored-by: Lorenze Jay <63378463+lorenzejay@users.noreply.github.com> --- src/crewai/agents/crew_agent_executor.py | 72 ++++++-- src/crewai/task.py | 6 +- src/crewai/telemetry/telemetry.py | 172 +++++++++++++++++- src/crewai/tools/tool_usage.py | 57 +++++- .../utilities/evaluators/task_evaluator.py | 2 +- src/crewai/utilities/events/agent_events.py | 27 +++ src/crewai/utilities/events/base_events.py | 4 + src/crewai/utilities/events/crew_events.py | 90 +++++++++ src/crewai/utilities/events/task_events.py | 42 ++++- .../utilities/events/tool_usage_events.py | 22 ++- 10 files changed, 458 insertions(+), 36 deletions(-) diff --git a/src/crewai/agents/crew_agent_executor.py b/src/crewai/agents/crew_agent_executor.py index bb17cd095..eb0cb22ad 100644 --- a/src/crewai/agents/crew_agent_executor.py +++ b/src/crewai/agents/crew_agent_executor.py @@ -20,7 +20,6 @@ from crewai.utilities import I18N, Printer from crewai.utilities.constants import MAX_LLM_RETRY, TRAINING_DATA_FILE from crewai.utilities.events import ( ToolUsageErrorEvent, - ToolUsageStartedEvent, crewai_event_bus, ) from crewai.utilities.events.tool_usage_events import ToolUsageStartedEvent @@ -153,8 +152,21 @@ class CrewAgentExecutor(CrewAgentExecutorMixin): formatted_answer = self._process_llm_response(answer) if isinstance(formatted_answer, AgentAction): + # Extract agent fingerprint if available + fingerprint_context = {} + if ( + self.agent + and hasattr(self.agent, "security_config") + and hasattr(self.agent.security_config, "fingerprint") + ): + fingerprint_context = { + "agent_fingerprint": str( + self.agent.security_config.fingerprint + ) + } + tool_result = self._execute_tool_and_check_finality( - formatted_answer + formatted_answer, fingerprint_context=fingerprint_context ) formatted_answer = self._handle_agent_action( formatted_answer, tool_result @@ -360,19 +372,35 @@ class CrewAgentExecutor(CrewAgentExecutorMixin): content=f"\033[95m## Final Answer:\033[00m \033[92m\n{formatted_answer.output}\033[00m\n\n" ) - def _execute_tool_and_check_finality(self, agent_action: AgentAction) -> ToolResult: + def _execute_tool_and_check_finality( + self, + agent_action: AgentAction, + fingerprint_context: Optional[Dict[str, str]] = None, + ) -> ToolResult: try: + fingerprint_context = fingerprint_context or {} + if self.agent: + # Create tool usage event with fingerprint information + event_data = { + "agent_key": self.agent.key, + "agent_role": self.agent.role, + "tool_name": agent_action.tool, + "tool_args": agent_action.tool_input, + "tool_class": agent_action.tool, + "agent": self.agent, # Pass the agent object for fingerprint extraction + } + + # Include fingerprint context + if fingerprint_context: + event_data.update(fingerprint_context) + + # Emit the tool usage started event with agent information crewai_event_bus.emit( self, - event=ToolUsageStartedEvent( - agent_key=self.agent.key, - agent_role=self.agent.role, - tool_name=agent_action.tool, - tool_args=agent_action.tool_input, - tool_class=agent_action.tool, - ), + event=ToolUsageStartedEvent(**event_data), ) + tool_usage = ToolUsage( tools_handler=self.tools_handler, tools=self.tools, @@ -383,6 +411,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin): task=self.task, # type: ignore[arg-type] agent=self.agent, action=agent_action, + fingerprint_context=fingerprint_context, # Pass fingerprint context ) tool_calling = tool_usage.parse_tool_calling(agent_action.text) @@ -411,16 +440,23 @@ class CrewAgentExecutor(CrewAgentExecutorMixin): except Exception as e: # TODO: drop if self.agent: + error_event_data = { + "agent_key": self.agent.key, + "agent_role": self.agent.role, + "tool_name": agent_action.tool, + "tool_args": agent_action.tool_input, + "tool_class": agent_action.tool, + "error": str(e), + "agent": self.agent, # Pass the agent object for fingerprint extraction + } + + # Include fingerprint context + if fingerprint_context: + error_event_data.update(fingerprint_context) + crewai_event_bus.emit( self, - event=ToolUsageErrorEvent( # validation error - agent_key=self.agent.key, - agent_role=self.agent.role, - tool_name=agent_action.tool, - tool_args=agent_action.tool_input, - tool_class=agent_action.tool, - error=str(e), - ), + event=ToolUsageErrorEvent(**error_event_data), ) raise e diff --git a/src/crewai/task.py b/src/crewai/task.py index c74e0081e..9874b5100 100644 --- a/src/crewai/task.py +++ b/src/crewai/task.py @@ -388,7 +388,7 @@ class Task(BaseModel): tools = tools or self.tools or [] self.processed_by_agents.add(agent.role) - crewai_event_bus.emit(self, TaskStartedEvent(context=context)) + crewai_event_bus.emit(self, TaskStartedEvent(context=context, task=self)) result = agent.execute_task( task=self, context=context, @@ -464,11 +464,11 @@ class Task(BaseModel): ) ) self._save_file(content) - crewai_event_bus.emit(self, TaskCompletedEvent(output=task_output)) + crewai_event_bus.emit(self, TaskCompletedEvent(output=task_output, task=self)) return task_output except Exception as e: self.end_time = datetime.datetime.now() - crewai_event_bus.emit(self, TaskFailedEvent(error=str(e))) + crewai_event_bus.emit(self, TaskFailedEvent(error=str(e), task=self)) raise e # Re-raise the exception after emitting the event def prompt(self) -> str: diff --git a/src/crewai/telemetry/telemetry.py b/src/crewai/telemetry/telemetry.py index 559ca8d4f..edf4c886a 100644 --- a/src/crewai/telemetry/telemetry.py +++ b/src/crewai/telemetry/telemetry.py @@ -112,6 +112,23 @@ class Telemetry: self._add_attribute(span, "crew_memory", crew.memory) self._add_attribute(span, "crew_number_of_tasks", len(crew.tasks)) self._add_attribute(span, "crew_number_of_agents", len(crew.agents)) + + # Add fingerprint data + if hasattr(crew, "fingerprint") and crew.fingerprint: + self._add_attribute(span, "crew_fingerprint", crew.fingerprint.uuid_str) + self._add_attribute( + span, + "crew_fingerprint_created_at", + crew.fingerprint.created_at.isoformat(), + ) + # Add fingerprint metadata if it exists + if hasattr(crew.fingerprint, "metadata") and crew.fingerprint.metadata: + self._add_attribute( + span, + "crew_fingerprint_metadata", + json.dumps(crew.fingerprint.metadata), + ) + if crew.share_crew: self._add_attribute( span, @@ -129,17 +146,43 @@ class Telemetry: "max_rpm": agent.max_rpm, "i18n": agent.i18n.prompt_file, "function_calling_llm": ( - agent.function_calling_llm.model - if agent.function_calling_llm + getattr( + getattr(agent, "function_calling_llm", None), + "model", + "", + ) + if getattr(agent, "function_calling_llm", None) else "" ), "llm": agent.llm.model, "delegation_enabled?": agent.allow_delegation, - "allow_code_execution?": agent.allow_code_execution, - "max_retry_limit": agent.max_retry_limit, + "allow_code_execution?": getattr( + agent, "allow_code_execution", False + ), + "max_retry_limit": getattr(agent, "max_retry_limit", 3), "tools_names": [ tool.name.casefold() for tool in agent.tools or [] ], + # Add agent fingerprint data if sharing crew details + "fingerprint": ( + getattr( + getattr(agent, "fingerprint", None), + "uuid_str", + None, + ) + ), + "fingerprint_created_at": ( + created_at.isoformat() + if ( + created_at := getattr( + getattr(agent, "fingerprint", None), + "created_at", + None, + ) + ) + is not None + else None + ), } for agent in crew.agents ] @@ -169,6 +212,17 @@ class Telemetry: "tools_names": [ tool.name.casefold() for tool in task.tools or [] ], + # Add task fingerprint data if sharing crew details + "fingerprint": ( + task.fingerprint.uuid_str + if hasattr(task, "fingerprint") and task.fingerprint + else None + ), + "fingerprint_created_at": ( + task.fingerprint.created_at.isoformat() + if hasattr(task, "fingerprint") and task.fingerprint + else None + ), } for task in crew.tasks ] @@ -196,14 +250,20 @@ class Telemetry: "max_iter": agent.max_iter, "max_rpm": agent.max_rpm, "function_calling_llm": ( - agent.function_calling_llm.model - if agent.function_calling_llm + getattr( + getattr(agent, "function_calling_llm", None), + "model", + "", + ) + if getattr(agent, "function_calling_llm", None) else "" ), "llm": agent.llm.model, "delegation_enabled?": agent.allow_delegation, - "allow_code_execution?": agent.allow_code_execution, - "max_retry_limit": agent.max_retry_limit, + "allow_code_execution?": getattr( + agent, "allow_code_execution", False + ), + "max_retry_limit": getattr(agent, "max_retry_limit", 3), "tools_names": [ tool.name.casefold() for tool in agent.tools or [] ], @@ -252,6 +312,39 @@ class Telemetry: self._add_attribute(created_span, "task_key", task.key) self._add_attribute(created_span, "task_id", str(task.id)) + # Add fingerprint data + if hasattr(crew, "fingerprint") and crew.fingerprint: + self._add_attribute( + created_span, "crew_fingerprint", crew.fingerprint.uuid_str + ) + + if hasattr(task, "fingerprint") and task.fingerprint: + self._add_attribute( + created_span, "task_fingerprint", task.fingerprint.uuid_str + ) + self._add_attribute( + created_span, + "task_fingerprint_created_at", + task.fingerprint.created_at.isoformat(), + ) + # Add fingerprint metadata if it exists + if hasattr(task.fingerprint, "metadata") and task.fingerprint.metadata: + self._add_attribute( + created_span, + "task_fingerprint_metadata", + json.dumps(task.fingerprint.metadata), + ) + + # Add agent fingerprint if task has an assigned agent + if hasattr(task, "agent") and task.agent: + agent_fingerprint = getattr( + getattr(task.agent, "fingerprint", None), "uuid_str", None + ) + if agent_fingerprint: + self._add_attribute( + created_span, "agent_fingerprint", agent_fingerprint + ) + if crew.share_crew: self._add_attribute( created_span, "formatted_description", task.description @@ -270,6 +363,21 @@ class Telemetry: self._add_attribute(span, "task_key", task.key) self._add_attribute(span, "task_id", str(task.id)) + # Add fingerprint data to execution span + if hasattr(crew, "fingerprint") and crew.fingerprint: + self._add_attribute(span, "crew_fingerprint", crew.fingerprint.uuid_str) + + if hasattr(task, "fingerprint") and task.fingerprint: + self._add_attribute(span, "task_fingerprint", task.fingerprint.uuid_str) + + # Add agent fingerprint if task has an assigned agent + if hasattr(task, "agent") and task.agent: + agent_fingerprint = getattr( + getattr(task.agent, "fingerprint", None), "uuid_str", None + ) + if agent_fingerprint: + self._add_attribute(span, "agent_fingerprint", agent_fingerprint) + if crew.share_crew: self._add_attribute(span, "formatted_description", task.description) self._add_attribute( @@ -291,7 +399,12 @@ class Telemetry: Note: If share_crew is enabled, this will also record the task output """ + def operation(): + # Ensure fingerprint data is present on completion span + if hasattr(task, "fingerprint") and task.fingerprint: + self._add_attribute(span, "task_fingerprint", task.fingerprint.uuid_str) + if crew.share_crew: self._add_attribute( span, @@ -312,6 +425,7 @@ class Telemetry: tool_name (str): Name of the tool being repeatedly used attempts (int): Number of attempts made with this tool """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Tool Repeated Usage") @@ -329,14 +443,16 @@ class Telemetry: self._safe_telemetry_operation(operation) - def tool_usage(self, llm: Any, tool_name: str, attempts: int): + def tool_usage(self, llm: Any, tool_name: str, attempts: int, agent: Any = None): """Records the usage of a tool by an agent. Args: llm (Any): The language model being used tool_name (str): Name of the tool being used attempts (int): Number of attempts made with this tool + agent (Any, optional): The agent using the tool """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Tool Usage") @@ -349,17 +465,31 @@ class Telemetry: self._add_attribute(span, "attempts", attempts) if llm: self._add_attribute(span, "llm", llm.model) + + # Add agent fingerprint data if available + if agent and hasattr(agent, "fingerprint") and agent.fingerprint: + self._add_attribute( + span, "agent_fingerprint", agent.fingerprint.uuid_str + ) + if hasattr(agent, "role"): + self._add_attribute(span, "agent_role", agent.role) + span.set_status(Status(StatusCode.OK)) span.end() self._safe_telemetry_operation(operation) - def tool_usage_error(self, llm: Any): + def tool_usage_error( + self, llm: Any, agent: Any = None, tool_name: Optional[str] = None + ): """Records when a tool usage results in an error. Args: llm (Any): The language model being used when the error occurred + agent (Any, optional): The agent using the tool + tool_name (str, optional): Name of the tool that caused the error """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Tool Usage Error") @@ -370,6 +500,18 @@ class Telemetry: ) if llm: self._add_attribute(span, "llm", llm.model) + + if tool_name: + self._add_attribute(span, "tool_name", tool_name) + + # Add agent fingerprint data if available + if agent and hasattr(agent, "fingerprint") and agent.fingerprint: + self._add_attribute( + span, "agent_fingerprint", agent.fingerprint.uuid_str + ) + if hasattr(agent, "role"): + self._add_attribute(span, "agent_role", agent.role) + span.set_status(Status(StatusCode.OK)) span.end() @@ -386,6 +528,7 @@ class Telemetry: exec_time (int): Execution time in seconds model_name (str): Name of the model used """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Crew Individual Test Result") @@ -420,6 +563,7 @@ class Telemetry: inputs (dict[str, Any] | None): Input parameters for the test model_name (str): Name of the model used in testing """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Crew Test Execution") @@ -446,6 +590,7 @@ class Telemetry: def deploy_signup_error_span(self): """Records when an error occurs during the deployment signup process.""" + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Deploy Signup Error") @@ -460,6 +605,7 @@ class Telemetry: Args: uuid (Optional[str]): Unique identifier for the deployment """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Start Deployment") @@ -472,6 +618,7 @@ class Telemetry: def create_crew_deployment_span(self): """Records the creation of a new crew deployment.""" + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Create Crew Deployment") @@ -487,6 +634,7 @@ class Telemetry: uuid (Optional[str]): Unique identifier for the crew log_type (str, optional): Type of logs being retrieved. Defaults to "deployment". """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Get Crew Logs") @@ -504,6 +652,7 @@ class Telemetry: Args: uuid (Optional[str]): Unique identifier for the crew being removed """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Remove Crew") @@ -634,6 +783,7 @@ class Telemetry: Args: flow_name (str): Name of the flow being created """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Flow Creation") @@ -650,6 +800,7 @@ class Telemetry: flow_name (str): Name of the flow being plotted node_names (list[str]): List of node names in the flow """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Flow Plotting") @@ -667,6 +818,7 @@ class Telemetry: flow_name (str): Name of the flow being executed node_names (list[str]): List of nodes being executed in the flow """ + def operation(): tracer = trace.get_tracer("crewai.telemetry") span = tracer.start_span("Flow Execution") diff --git a/src/crewai/tools/tool_usage.py b/src/crewai/tools/tool_usage.py index edfedb4b8..66cb5f7e0 100644 --- a/src/crewai/tools/tool_usage.py +++ b/src/crewai/tools/tool_usage.py @@ -22,6 +22,7 @@ from crewai.utilities.events.tool_usage_events import ( ToolSelectionErrorEvent, ToolUsageErrorEvent, ToolUsageFinishedEvent, + ToolUsageStartedEvent, ToolValidateInputErrorEvent, ) @@ -69,6 +70,7 @@ class ToolUsage: function_calling_llm: Any, agent: Any, action: Any, + fingerprint_context: Optional[Dict[str, str]] = None, ) -> None: self._i18n: I18N = agent.i18n self._printer: Printer = Printer() @@ -85,6 +87,7 @@ class ToolUsage: self.task = task self.action = action self.function_calling_llm = function_calling_llm + self.fingerprint_context = fingerprint_context or {} # Set the maximum parsing attempts for bigger models if ( @@ -192,12 +195,18 @@ class ToolUsage: for k, v in calling.arguments.items() if k in acceptable_args } + # Add fingerprint metadata if available + arguments = self._add_fingerprint_metadata(arguments) result = tool.invoke(input=arguments) except Exception: arguments = calling.arguments + # Add fingerprint metadata if available + arguments = self._add_fingerprint_metadata(arguments) result = tool.invoke(input=arguments) else: - result = tool.invoke(input={}) + # Add fingerprint metadata even to empty arguments + arguments = self._add_fingerprint_metadata({}) + result = tool.invoke(input=arguments) except Exception as e: self.on_tool_error(tool=tool, tool_calling=calling, e=e) self._run_attempts += 1 @@ -486,8 +495,13 @@ class ToolUsage: "tool_name": self.action.tool, "tool_args": str(self.action.tool_input), "tool_class": self.__class__.__name__, + "agent": self.agent, # Adding agent for fingerprint extraction } + # Include fingerprint context if available + if self.fingerprint_context: + tool_selection_data.update(self.fingerprint_context) + crewai_event_bus.emit( self, ToolValidateInputErrorEvent(**tool_selection_data, error=final_error), @@ -518,7 +532,7 @@ class ToolUsage: crewai_event_bus.emit(self, ToolUsageFinishedEvent(**event_data)) def _prepare_event_data(self, tool: Any, tool_calling: ToolCalling) -> dict: - return { + event_data = { "agent_key": self.agent.key, "agent_role": (self.agent._original_role or self.agent.role), "run_attempts": self._run_attempts, @@ -526,4 +540,43 @@ class ToolUsage: "tool_name": tool.name, "tool_args": tool_calling.arguments, "tool_class": tool.__class__.__name__, + "agent": self.agent, # Adding agent for fingerprint extraction } + + # Include fingerprint context if available + if self.fingerprint_context: + event_data.update(self.fingerprint_context) + + return event_data + + def _add_fingerprint_metadata(self, arguments: dict) -> dict: + """Add fingerprint metadata to tool arguments if available. + + Args: + arguments: The original tool arguments + + Returns: + Updated arguments dictionary with fingerprint metadata + """ + # Create a shallow copy to avoid modifying the original + arguments = arguments.copy() + + # Add security metadata under a designated key + if not "security_context" in arguments: + arguments["security_context"] = {} + + security_context = arguments["security_context"] + + # Add agent fingerprint if available + if hasattr(self, "agent") and hasattr(self.agent, "security_config"): + security_context["agent_fingerprint"] = self.agent.security_config.fingerprint.to_dict() + + # Add task fingerprint if available + if hasattr(self, "task") and hasattr(self.task, "security_config"): + security_context["task_fingerprint"] = self.task.security_config.fingerprint.to_dict() + + # Add crew fingerprint if available + if hasattr(self, "crew") and hasattr(self.crew, "security_config"): + security_context["crew_fingerprint"] = self.crew.security_config.fingerprint.to_dict() + + return arguments diff --git a/src/crewai/utilities/evaluators/task_evaluator.py b/src/crewai/utilities/evaluators/task_evaluator.py index 2e9907bd7..6dde83c24 100644 --- a/src/crewai/utilities/evaluators/task_evaluator.py +++ b/src/crewai/utilities/evaluators/task_evaluator.py @@ -45,7 +45,7 @@ class TaskEvaluator: def evaluate(self, task, output) -> TaskEvaluation: crewai_event_bus.emit( - self, TaskEvaluationEvent(evaluation_type="task_evaluation") + self, TaskEvaluationEvent(evaluation_type="task_evaluation", task=task) ) evaluation_query = ( f"Assess the quality of the task completed based on the description, expected output, and actual results.\n\n" diff --git a/src/crewai/utilities/events/agent_events.py b/src/crewai/utilities/events/agent_events.py index ed0480957..3d325b41c 100644 --- a/src/crewai/utilities/events/agent_events.py +++ b/src/crewai/utilities/events/agent_events.py @@ -21,6 +21,15 @@ class AgentExecutionStartedEvent(CrewEvent): model_config = {"arbitrary_types_allowed": True} + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the agent + if hasattr(self.agent, 'fingerprint') and self.agent.fingerprint: + self.source_fingerprint = self.agent.fingerprint.uuid_str + self.source_type = "agent" + if hasattr(self.agent.fingerprint, 'metadata') and self.agent.fingerprint.metadata: + self.fingerprint_metadata = self.agent.fingerprint.metadata + class AgentExecutionCompletedEvent(CrewEvent): """Event emitted when an agent completes executing a task""" @@ -30,6 +39,15 @@ class AgentExecutionCompletedEvent(CrewEvent): output: str type: str = "agent_execution_completed" + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the agent + if hasattr(self.agent, 'fingerprint') and self.agent.fingerprint: + self.source_fingerprint = self.agent.fingerprint.uuid_str + self.source_type = "agent" + if hasattr(self.agent.fingerprint, 'metadata') and self.agent.fingerprint.metadata: + self.fingerprint_metadata = self.agent.fingerprint.metadata + class AgentExecutionErrorEvent(CrewEvent): """Event emitted when an agent encounters an error during execution""" @@ -38,3 +56,12 @@ class AgentExecutionErrorEvent(CrewEvent): task: Any error: str type: str = "agent_execution_error" + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the agent + if hasattr(self.agent, 'fingerprint') and self.agent.fingerprint: + self.source_fingerprint = self.agent.fingerprint.uuid_str + self.source_type = "agent" + if hasattr(self.agent.fingerprint, 'metadata') and self.agent.fingerprint.metadata: + self.fingerprint_metadata = self.agent.fingerprint.metadata diff --git a/src/crewai/utilities/events/base_events.py b/src/crewai/utilities/events/base_events.py index b29ae6fb6..52e600f5f 100644 --- a/src/crewai/utilities/events/base_events.py +++ b/src/crewai/utilities/events/base_events.py @@ -1,4 +1,5 @@ from datetime import datetime +from typing import Any, Dict, Optional from pydantic import BaseModel, Field @@ -8,3 +9,6 @@ class CrewEvent(BaseModel): timestamp: datetime = Field(default_factory=datetime.now) type: str + source_fingerprint: Optional[str] = None # UUID string of the source entity + source_type: Optional[str] = None # "agent", "task", "crew" + fingerprint_metadata: Optional[Dict[str, Any]] = None # Any relevant metadata diff --git a/src/crewai/utilities/events/crew_events.py b/src/crewai/utilities/events/crew_events.py index 13dfd8e34..4a10772a8 100644 --- a/src/crewai/utilities/events/crew_events.py +++ b/src/crewai/utilities/events/crew_events.py @@ -11,6 +11,16 @@ class CrewKickoffStartedEvent(CrewEvent): crew_name: Optional[str] inputs: Optional[Dict[str, Any]] type: str = "crew_kickoff_started" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata class CrewKickoffCompletedEvent(CrewEvent): @@ -19,6 +29,16 @@ class CrewKickoffCompletedEvent(CrewEvent): crew_name: Optional[str] output: Any type: str = "crew_kickoff_completed" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata class CrewKickoffFailedEvent(CrewEvent): @@ -27,6 +47,16 @@ class CrewKickoffFailedEvent(CrewEvent): error: str crew_name: Optional[str] type: str = "crew_kickoff_failed" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata class CrewTrainStartedEvent(CrewEvent): @@ -37,6 +67,16 @@ class CrewTrainStartedEvent(CrewEvent): filename: str inputs: Optional[Dict[str, Any]] type: str = "crew_train_started" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata class CrewTrainCompletedEvent(CrewEvent): @@ -46,6 +86,16 @@ class CrewTrainCompletedEvent(CrewEvent): n_iterations: int filename: str type: str = "crew_train_completed" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata class CrewTrainFailedEvent(CrewEvent): @@ -54,6 +104,16 @@ class CrewTrainFailedEvent(CrewEvent): error: str crew_name: Optional[str] type: str = "crew_train_failed" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata class CrewTestStartedEvent(CrewEvent): @@ -64,6 +124,16 @@ class CrewTestStartedEvent(CrewEvent): eval_llm: Optional[Union[str, Any]] inputs: Optional[Dict[str, Any]] type: str = "crew_test_started" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata class CrewTestCompletedEvent(CrewEvent): @@ -71,6 +141,16 @@ class CrewTestCompletedEvent(CrewEvent): crew_name: Optional[str] type: str = "crew_test_completed" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata class CrewTestFailedEvent(CrewEvent): @@ -79,3 +159,13 @@ class CrewTestFailedEvent(CrewEvent): error: str crew_name: Optional[str] type: str = "crew_test_failed" + crew: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the crew + if self.crew and hasattr(self.crew, 'fingerprint') and self.crew.fingerprint: + self.source_fingerprint = self.crew.fingerprint.uuid_str + self.source_type = "crew" + if hasattr(self.crew.fingerprint, 'metadata') and self.crew.fingerprint.metadata: + self.fingerprint_metadata = self.crew.fingerprint.metadata diff --git a/src/crewai/utilities/events/task_events.py b/src/crewai/utilities/events/task_events.py index d81b7ce2d..7c7bb8964 100644 --- a/src/crewai/utilities/events/task_events.py +++ b/src/crewai/utilities/events/task_events.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Any, Optional from crewai.tasks.task_output import TaskOutput from crewai.utilities.events.base_events import CrewEvent @@ -9,6 +9,16 @@ class TaskStartedEvent(CrewEvent): type: str = "task_started" context: Optional[str] + task: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the task + if hasattr(self.task, 'fingerprint') and self.task.fingerprint: + self.source_fingerprint = self.task.fingerprint.uuid_str + self.source_type = "task" + if hasattr(self.task.fingerprint, 'metadata') and self.task.fingerprint.metadata: + self.fingerprint_metadata = self.task.fingerprint.metadata class TaskCompletedEvent(CrewEvent): @@ -16,6 +26,16 @@ class TaskCompletedEvent(CrewEvent): output: TaskOutput type: str = "task_completed" + task: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the task + if hasattr(self.task, 'fingerprint') and self.task.fingerprint: + self.source_fingerprint = self.task.fingerprint.uuid_str + self.source_type = "task" + if hasattr(self.task.fingerprint, 'metadata') and self.task.fingerprint.metadata: + self.fingerprint_metadata = self.task.fingerprint.metadata class TaskFailedEvent(CrewEvent): @@ -23,6 +43,16 @@ class TaskFailedEvent(CrewEvent): error: str type: str = "task_failed" + task: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the task + if hasattr(self.task, 'fingerprint') and self.task.fingerprint: + self.source_fingerprint = self.task.fingerprint.uuid_str + self.source_type = "task" + if hasattr(self.task.fingerprint, 'metadata') and self.task.fingerprint.metadata: + self.fingerprint_metadata = self.task.fingerprint.metadata class TaskEvaluationEvent(CrewEvent): @@ -30,3 +60,13 @@ class TaskEvaluationEvent(CrewEvent): type: str = "task_evaluation" evaluation_type: str + task: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the task + if hasattr(self.task, 'fingerprint') and self.task.fingerprint: + self.source_fingerprint = self.task.fingerprint.uuid_str + self.source_type = "task" + if hasattr(self.task.fingerprint, 'metadata') and self.task.fingerprint.metadata: + self.fingerprint_metadata = self.task.fingerprint.metadata diff --git a/src/crewai/utilities/events/tool_usage_events.py b/src/crewai/utilities/events/tool_usage_events.py index e5027832c..d4202f563 100644 --- a/src/crewai/utilities/events/tool_usage_events.py +++ b/src/crewai/utilities/events/tool_usage_events.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Callable, Dict +from typing import Any, Callable, Dict, Optional from .base_events import CrewEvent @@ -14,9 +14,19 @@ class ToolUsageEvent(CrewEvent): tool_class: str run_attempts: int | None = None delegations: int | None = None + agent: Optional[Any] = None model_config = {"arbitrary_types_allowed": True} + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the agent + if self.agent and hasattr(self.agent, 'fingerprint') and self.agent.fingerprint: + self.source_fingerprint = self.agent.fingerprint.uuid_str + self.source_type = "agent" + if hasattr(self.agent.fingerprint, 'metadata') and self.agent.fingerprint.metadata: + self.fingerprint_metadata = self.agent.fingerprint.metadata + class ToolUsageStartedEvent(ToolUsageEvent): """Event emitted when a tool execution is started""" @@ -63,3 +73,13 @@ class ToolExecutionErrorEvent(CrewEvent): tool_name: str tool_args: Dict[str, Any] tool_class: Callable + agent: Optional[Any] = None + + def __init__(self, **data): + super().__init__(**data) + # Set fingerprint data from the agent + if self.agent and hasattr(self.agent, 'fingerprint') and self.agent.fingerprint: + self.source_fingerprint = self.agent.fingerprint.uuid_str + self.source_type = "agent" + if hasattr(self.agent.fingerprint, 'metadata') and self.agent.fingerprint.metadata: + self.fingerprint_metadata = self.agent.fingerprint.metadata