WIP crew events emitter

This commit is contained in:
Lorenze Jay
2025-02-06 11:06:43 -08:00
parent a950e67c7d
commit 95bae8bba3
21 changed files with 2499 additions and 113 deletions

View File

@@ -19,6 +19,12 @@ from crewai.tools.base_tool import Tool
from crewai.utilities import Converter, Prompts
from crewai.utilities.constants import TRAINED_AGENTS_DATA_FILE, TRAINING_DATA_FILE
from crewai.utilities.converter import generate_model_description
from crewai.utilities.events.agent_events import (
AgentExecutionCompleted,
AgentExecutionError,
AgentExecutionStarted,
)
from crewai.utilities.events.events import emit
from crewai.utilities.llm_utils import create_llm
from crewai.utilities.token_counter_callback import TokenCalcHandler
from crewai.utilities.training_handler import CrewTrainingHandler
@@ -182,6 +188,7 @@ class Agent(BaseAgent):
Returns:
Output of the agent
"""
emit(self, event=AgentExecutionStarted(agent=self, task=task))
if self.tools_handler:
self.tools_handler.last_used_tool = {} # type: ignore # Incompatible types in assignment (expression has type "dict[Never, Never]", variable has type "ToolCalling")
@@ -259,6 +266,9 @@ class Agent(BaseAgent):
raise e
self._times_executed += 1
if self._times_executed > self.max_retry_limit:
emit(
self, event=AgentExecutionError(agent=self, task=task, error=str(e))
)
raise e
result = self.execute_task(task, context, tools)
@@ -271,7 +281,7 @@ class Agent(BaseAgent):
for tool_result in self.tools_results: # type: ignore # Item "None" of "list[Any] | None" has no attribute "__iter__" (not iterable)
if tool_result.get("result_as_answer", False):
result = tool_result["result"]
emit(self, event=AgentExecutionCompleted(agent=self, task=task, output=result))
return result
def create_agent_executor(

View File

@@ -43,6 +43,18 @@ from crewai.utilities import I18N, FileHandler, Logger, RPMController
from crewai.utilities.constants import TRAINING_DATA_FILE
from crewai.utilities.evaluators.crew_evaluator_handler import CrewEvaluator
from crewai.utilities.evaluators.task_evaluator import TaskEvaluator
from crewai.utilities.events import event_bus
from crewai.utilities.events.crew_events import (
CrewKickoffCompleted,
CrewKickoffFailed,
CrewKickoffStarted,
CrewTrainStarted,
CrewTrainCompleted,
CrewTrainFailed,
CrewTestStarted,
CrewTestCompleted,
CrewTestFailed,
)
from crewai.utilities.formatter import (
aggregate_raw_outputs_from_task_outputs,
aggregate_raw_outputs_from_tasks,
@@ -215,6 +227,10 @@ class Crew(BaseModel):
default=None,
description="Knowledge for the crew.",
)
listen_to_events: Optional[bool] = Field(
default=True,
description="Whether the crew should listen to events.",
)
@field_validator("id", mode="before")
@classmethod
@@ -491,10 +507,19 @@ class Crew(BaseModel):
self, n_iterations: int, filename: str, inputs: Optional[Dict[str, Any]] = {}
) -> None:
"""Trains the crew for a given number of iterations."""
train_crew = self.copy()
train_crew._setup_for_training(filename)
try:
event_bus.emit(
self,
CrewTrainStarted(
crew_name=self.name or "crew",
n_iterations=n_iterations,
filename=filename,
inputs=inputs,
),
)
train_crew = self.copy()
train_crew._setup_for_training(filename)
for n_iteration in range(n_iterations):
train_crew._train_iteration = n_iteration
train_crew.kickoff(inputs=inputs)
@@ -509,7 +534,17 @@ class Crew(BaseModel):
CrewTrainingHandler(filename).save_trained_data(
agent_id=str(agent.role), trained_data=result.model_dump()
)
event_bus.emit(
self,
CrewTrainCompleted(
crew_name=self.name or "crew",
n_iterations=n_iterations,
filename=filename,
),
)
except Exception as e:
event_bus.emit(self, CrewTrainFailed(error=str(e)))
self._logger.log("error", f"Training failed: {e}", color="red")
CrewTrainingHandler(TRAINING_DATA_FILE).clear()
CrewTrainingHandler(filename).clear()
@@ -519,60 +554,67 @@ class Crew(BaseModel):
self,
inputs: Optional[Dict[str, Any]] = None,
) -> CrewOutput:
for before_callback in self.before_kickoff_callbacks:
if inputs is None:
inputs = {}
inputs = before_callback(inputs)
try:
for before_callback in self.before_kickoff_callbacks:
if inputs is None:
inputs = {}
inputs = before_callback(inputs)
"""Starts the crew to work on its assigned tasks."""
self._execution_span = self._telemetry.crew_execution_span(self, inputs)
self._task_output_handler.reset()
self._logging_color = "bold_purple"
if inputs is not None:
self._inputs = inputs
self._interpolate_inputs(inputs)
self._set_tasks_callbacks()
i18n = I18N(prompt_file=self.prompt_file)
for agent in self.agents:
agent.i18n = i18n
# type: ignore[attr-defined] # Argument 1 to "_interpolate_inputs" of "Crew" has incompatible type "dict[str, Any] | None"; expected "dict[str, Any]"
agent.crew = self # type: ignore[attr-defined]
# TODO: Create an AgentFunctionCalling protocol for future refactoring
if not agent.function_calling_llm: # type: ignore # "BaseAgent" has no attribute "function_calling_llm"
agent.function_calling_llm = self.function_calling_llm # type: ignore # "BaseAgent" has no attribute "function_calling_llm"
if not agent.step_callback: # type: ignore # "BaseAgent" has no attribute "step_callback"
agent.step_callback = self.step_callback # type: ignore # "BaseAgent" has no attribute "step_callback"
agent.create_agent_executor()
if self.planning:
self._handle_crew_planning()
metrics: List[UsageMetrics] = []
if self.process == Process.sequential:
result = self._run_sequential_process()
elif self.process == Process.hierarchical:
result = self._run_hierarchical_process()
else:
raise NotImplementedError(
f"The process '{self.process}' is not implemented yet."
event_bus.emit(
self, CrewKickoffStarted(crew_name=self.name or "crew", inputs=inputs)
)
for after_callback in self.after_kickoff_callbacks:
result = after_callback(result)
"""Starts the crew to work on its assigned tasks."""
# self._execution_span = self._telemetry.crew_execution_span(self, inputs) # TODO: drop this
self._task_output_handler.reset()
self._logging_color = "bold_purple"
metrics += [agent._token_process.get_summary() for agent in self.agents]
if inputs is not None:
self._inputs = inputs
self._interpolate_inputs(inputs)
self._set_tasks_callbacks()
self.usage_metrics = UsageMetrics()
for metric in metrics:
self.usage_metrics.add_usage_metrics(metric)
i18n = I18N(prompt_file=self.prompt_file)
return result
for agent in self.agents:
agent.i18n = i18n
# type: ignore[attr-defined] # Argument 1 to "_interpolate_inputs" of "Crew" has incompatible type "dict[str, Any] | None"; expected "dict[str, Any]"
agent.crew = self # type: ignore[attr-defined]
# TODO: Create an AgentFunctionCalling protocol for future refactoring
if not agent.function_calling_llm: # type: ignore # "BaseAgent" has no attribute "function_calling_llm"
agent.function_calling_llm = self.function_calling_llm # type: ignore # "BaseAgent" has no attribute "function_calling_llm"
if not agent.step_callback: # type: ignore # "BaseAgent" has no attribute "step_callback"
agent.step_callback = self.step_callback # type: ignore # "BaseAgent" has no attribute "step_callback"
agent.create_agent_executor()
if self.planning:
self._handle_crew_planning()
metrics: List[UsageMetrics] = []
if self.process == Process.sequential:
result = self._run_sequential_process()
elif self.process == Process.hierarchical:
result = self._run_hierarchical_process()
else:
raise NotImplementedError(
f"The process '{self.process}' is not implemented yet."
)
for after_callback in self.after_kickoff_callbacks:
result = after_callback(result)
metrics += [agent._token_process.get_summary() for agent in self.agents]
self.usage_metrics = UsageMetrics()
for metric in metrics:
self.usage_metrics.add_usage_metrics(metric)
return result
except Exception as e:
event_bus.emit(self, CrewKickoffFailed(error=str(e)))
raise
def kickoff_for_each(self, inputs: List[Dict[str, Any]]) -> List[CrewOutput]:
"""Executes the Crew's workflow for each input in the list and aggregates results."""
@@ -920,7 +962,12 @@ class Crew(BaseModel):
final_string_output = final_task_output.raw
self._finish_execution(final_string_output)
token_usage = self.calculate_usage_metrics()
event_bus.emit(
self,
CrewKickoffCompleted(
crew_name=self.name or "crew", output=final_task_output
),
)
return CrewOutput(
raw=final_task_output.raw,
pydantic=final_task_output.pydantic,
@@ -1112,7 +1159,7 @@ class Crew(BaseModel):
end_state_reason="Finished Execution",
is_auto_end=True,
)
self._telemetry.end_crew(self, final_string_output)
# self._telemetry.end_crew(self, final_string_output)
def calculate_usage_metrics(self) -> UsageMetrics:
"""Calculates and returns the usage metrics."""
@@ -1134,21 +1181,42 @@ class Crew(BaseModel):
inputs: Optional[Dict[str, Any]] = None,
) -> None:
"""Test and evaluate the Crew with the given inputs for n iterations concurrently using concurrent.futures."""
test_crew = self.copy()
try:
event_bus.emit(
self,
CrewTestStarted(
crew_name=self.name or "crew",
n_iterations=n_iterations,
openai_model_name=openai_model_name,
inputs=inputs,
),
)
test_crew = self.copy()
# TODO: drop this
# self._test_execution_span = test_crew._telemetry.test_execution_span(
# test_crew,
# n_iterations,
# inputs,
# openai_model_name,
# )
evaluator = CrewEvaluator(test_crew, openai_model_name)
self._test_execution_span = test_crew._telemetry.test_execution_span(
test_crew,
n_iterations,
inputs,
openai_model_name, # type: ignore[arg-type]
) # type: ignore[arg-type]
evaluator = CrewEvaluator(test_crew, openai_model_name) # type: ignore[arg-type]
for i in range(1, n_iterations + 1):
evaluator.set_iteration(i)
test_crew.kickoff(inputs=inputs)
for i in range(1, n_iterations + 1):
evaluator.set_iteration(i)
test_crew.kickoff(inputs=inputs)
evaluator.print_crew_evaluation_result()
evaluator.print_crew_evaluation_result()
event_bus.emit(
self,
CrewTestCompleted(
crew_name=self.name or "crew",
n_iterations=n_iterations,
),
)
except Exception as e:
event_bus.emit(self, CrewTestFailed(error=str(e)))
raise
def __repr__(self):
return f"Crew(id={self.id}, process={self.process}, number_of_agents={len(self.agents)}, number_of_tasks={len(self.tasks)})"

View File

@@ -19,16 +19,17 @@ from uuid import uuid4
from blinker import Signal
from pydantic import BaseModel, Field, ValidationError
from crewai.flow.flow_events import (
FlowFinishedEvent,
FlowStartedEvent,
MethodExecutionFinishedEvent,
MethodExecutionStartedEvent,
)
from crewai.flow.flow_visualizer import plot_flow
from crewai.flow.persistence.base import FlowPersistence
from crewai.flow.utils import get_possible_return_constants
from crewai.telemetry import Telemetry
from crewai.utilities.events import (
FlowFinished,
FlowStarted,
MethodExecutionFinished,
MethodExecutionStarted,
event_bus,
)
from crewai.utilities.printer import Printer
logger = logging.getLogger(__name__)
@@ -394,7 +395,6 @@ class FlowMeta(type):
or hasattr(attr_value, "__trigger_methods__")
or hasattr(attr_value, "__is_router__")
):
# Register start methods
if hasattr(attr_value, "__is_start_method__"):
start_methods.append(attr_name)
@@ -600,7 +600,7 @@ class Flow(Generic[T], metaclass=FlowMeta):
```
"""
try:
if not hasattr(self, '_state'):
if not hasattr(self, "_state"):
return ""
if isinstance(self._state, dict):
@@ -706,40 +706,47 @@ class Flow(Generic[T], metaclass=FlowMeta):
inputs: Optional dictionary containing input values and potentially a state ID to restore
"""
# Handle state restoration if ID is provided in inputs
if inputs and 'id' in inputs and self._persistence is not None:
restore_uuid = inputs['id']
if inputs and "id" in inputs and self._persistence is not None:
restore_uuid = inputs["id"]
stored_state = self._persistence.load_state(restore_uuid)
# Override the id in the state if it exists in inputs
if 'id' in inputs:
if "id" in inputs:
if isinstance(self._state, dict):
self._state['id'] = inputs['id']
self._state["id"] = inputs["id"]
elif isinstance(self._state, BaseModel):
setattr(self._state, 'id', inputs['id'])
setattr(self._state, "id", inputs["id"])
if stored_state:
self._log_flow_event(f"Loading flow state from memory for UUID: {restore_uuid}", color="yellow")
self._log_flow_event(
f"Loading flow state from memory for UUID: {restore_uuid}",
color="yellow",
)
# Restore the state
self._restore_state(stored_state)
else:
self._log_flow_event(f"No flow state found for UUID: {restore_uuid}", color="red")
self._log_flow_event(
f"No flow state found for UUID: {restore_uuid}", color="red"
)
# Apply any additional inputs after restoration
filtered_inputs = {k: v for k, v in inputs.items() if k != 'id'}
filtered_inputs = {k: v for k, v in inputs.items() if k != "id"}
if filtered_inputs:
self._initialize_state(filtered_inputs)
# Start flow execution
self.event_emitter.send(
event_bus.emit(
self,
event=FlowStartedEvent(
FlowStarted(
type="flow_started",
flow_name=self.__class__.__name__,
),
)
self._log_flow_event(f"Flow started with ID: {self.flow_id}", color="bold_magenta")
self._log_flow_event(
f"Flow started with ID: {self.flow_id}", color="bold_magenta"
)
if inputs is not None and 'id' not in inputs:
if inputs is not None and "id" not in inputs:
self._initialize_state(inputs)
return asyncio.run(self.kickoff_async())
@@ -760,9 +767,9 @@ class Flow(Generic[T], metaclass=FlowMeta):
final_output = self._method_outputs[-1] if self._method_outputs else None
self.event_emitter.send(
event_bus.emit(
self,
event=FlowFinishedEvent(
FlowFinished(
type="flow_finished",
flow_name=self.__class__.__name__,
result=final_output,
@@ -944,9 +951,9 @@ class Flow(Generic[T], metaclass=FlowMeta):
try:
method = self._methods[listener_name]
self.event_emitter.send(
event_bus.emit(
self,
event=MethodExecutionStartedEvent(
MethodExecutionStarted(
type="method_execution_started",
method_name=listener_name,
flow_name=self.__class__.__name__,
@@ -964,9 +971,9 @@ class Flow(Generic[T], metaclass=FlowMeta):
else:
listener_result = await self._execute_method(listener_name, method)
self.event_emitter.send(
event_bus.emit(
self,
event=MethodExecutionFinishedEvent(
MethodExecutionFinished(
type="method_execution_finished",
method_name=listener_name,
flow_name=self.__class__.__name__,
@@ -984,7 +991,9 @@ class Flow(Generic[T], metaclass=FlowMeta):
traceback.print_exc()
def _log_flow_event(self, message: str, color: str = "yellow", level: str = "info") -> None:
def _log_flow_event(
self, message: str, color: str = "yellow", level: str = "info"
) -> None:
"""Centralized logging method for flow events.
This method provides a consistent interface for logging flow-related events,

View File

@@ -40,6 +40,8 @@ from crewai.telemetry.telemetry import Telemetry
from crewai.tools.base_tool import BaseTool
from crewai.utilities.config import process_config
from crewai.utilities.converter import Converter, convert_to_model
from crewai.utilities.events.events import emit
from crewai.utilities.events.task_events import TaskCompleted, TaskStarted
from crewai.utilities.i18n import I18N
from crewai.utilities.printer import Printer
@@ -348,6 +350,7 @@ class Task(BaseModel):
tools: Optional[List[Any]],
) -> TaskOutput:
"""Run the core execution logic of the task."""
agent = agent or self.agent
self.agent = agent
if not agent:
@@ -362,7 +365,7 @@ class Task(BaseModel):
tools = tools or self.tools or []
self.processed_by_agents.add(agent.role)
emit(self, TaskStarted(task=self))
result = agent.execute_task(
task=self,
context=context,
@@ -436,7 +439,7 @@ class Task(BaseModel):
else result
)
self._save_file(content)
emit(self, TaskCompleted(task=self, output=task_output))
return task_output
def prompt(self) -> str:

View File

@@ -10,7 +10,7 @@ from typing import Any, Dict, List, Optional, Union
import json5
from json_repair import repair_json
import crewai.utilities.events as events
import crewai.utilities.events.events as events
from crewai.agents.tools_handler import ToolsHandler
from crewai.task import Task
from crewai.telemetry import Telemetry
@@ -116,7 +116,10 @@ class ToolUsage:
self._printer.print(content=f"\n\n{error}\n", color="red")
return error
if isinstance(tool, CrewStructuredTool) and tool.name == self._i18n.tools("add_image")["name"]: # type: ignore
if (
isinstance(tool, CrewStructuredTool)
and tool.name == self._i18n.tools("add_image")["name"]
): # type: ignore
try:
result = self._use(tool_string=tool_string, tool=tool, calling=calling)
return result
@@ -181,7 +184,9 @@ class ToolUsage:
if calling.arguments:
try:
acceptable_args = tool.args_schema.model_json_schema()["properties"].keys() # type: ignore
acceptable_args = tool.args_schema.model_json_schema()[
"properties"
].keys() # type: ignore
arguments = {
k: v
for k, v in calling.arguments.items()
@@ -460,9 +465,7 @@ class ToolUsage:
def on_tool_error(self, tool: Any, tool_calling: ToolCalling, e: Exception) -> None:
event_data = self._prepare_event_data(tool, tool_calling)
events.emit(
source=self, event=ToolUsageError(**{**event_data, "error": str(e)})
)
events.emit(self, event=ToolUsageError(**{**event_data, "error": str(e)}))
def on_tool_use_finished(
self, tool: Any, tool_calling: ToolCalling, from_cache: bool, started_at: float
@@ -476,7 +479,7 @@ class ToolUsage:
"from_cache": from_cache,
}
)
events.emit(source=self, event=ToolUsageFinished(**event_data))
events.emit(self, event=ToolUsageFinished(**event_data))
def _prepare_event_data(self, tool: Any, tool_calling: ToolCalling) -> dict:
return {

View File

@@ -0,0 +1,36 @@
from .crew_events import (
CrewKickoffStarted,
CrewKickoffCompleted,
CrewKickoffFailed,
)
from .agent_events import AgentExecutionStarted, AgentExecutionCompleted
from .task_events import TaskStarted, TaskCompleted
from .flow_events import FlowStarted, FlowFinished, MethodExecutionStarted, MethodExecutionFinished
from .event_bus import event_bus, EventTypes
from .events import emit, on
from .event_bus import EventBus
from .event_listener import EventListener
event_bus = EventBus()
event_listener = EventListener()
__all__ = [
AgentExecutionStarted,
AgentExecutionCompleted,
CrewKickoffStarted,
CrewKickoffCompleted,
CrewKickoffFailed,
TaskStarted,
TaskCompleted,
FlowStarted,
FlowFinished,
MethodExecutionStarted,
MethodExecutionFinished,
EventTypes,
emit,
on,
event_bus
]

View File

@@ -0,0 +1,35 @@
from typing import Any
from .crew_events import CrewEvent
class AgentExecutionStarted(CrewEvent):
"""Event emitted when an agent starts executing a task"""
agent: Any # type: ignore
task: Any # type: ignore
type: str = "agent_execution_started"
model_config = {"arbitrary_types_allowed": True}
class AgentExecutionCompleted(CrewEvent):
"""Event emitted when an agent completes executing a task"""
agent: Any
task: Any
output: str
type: str = "agent_execution_completed"
model_config = {"arbitrary_types_allowed": True}
class AgentExecutionError(CrewEvent):
"""Event emitted when an agent encounters an error during execution"""
agent: Any
task: Any
error: str
type: str = "agent_execution_error"
model_config = {"arbitrary_types_allowed": True}

View File

@@ -0,0 +1,91 @@
from datetime import datetime
from enum import Enum
from typing import Any, Dict, Optional
from pydantic import BaseModel, Field
class RunType(Enum):
KICKOFF = "kickoff"
TEST = "test"
TRAIN = "train"
class CrewEvent(BaseModel):
"""Base class for all crew events"""
timestamp: datetime = Field(default_factory=datetime.now)
type: str
class CrewKickoffStarted(CrewEvent):
"""Event emitted when a crew starts execution"""
crew_name: Optional[str]
inputs: Optional[Dict[str, Any]]
type: str = "crew_kickoff_started"
class CrewKickoffCompleted(CrewEvent):
"""Event emitted when a crew completes execution"""
crew_name: Optional[str]
output: Any
type: str = "crew_kickoff_completed"
class CrewKickoffFailed(CrewEvent):
"""Event emitted when a crew fails to complete execution"""
error: str
type: str = "crew_kickoff_failed"
class CrewTrainStarted(CrewEvent):
"""Event emitted when a crew starts training"""
crew_name: Optional[str]
n_iterations: int
filename: str
inputs: Optional[Dict[str, Any]]
type: str = "crew_train_started"
class CrewTrainCompleted(CrewEvent):
"""Event emitted when a crew completes training"""
crew_name: Optional[str]
n_iterations: int
filename: str
type: str = "crew_train_completed"
class CrewTrainFailed(CrewEvent):
"""Event emitted when a crew fails to complete training"""
error: str
type: str = "crew_train_failed"
class CrewTestStarted(CrewEvent):
"""Event emitted when a crew starts testing"""
crew_name: Optional[str]
n_iterations: int
openai_model_name: Optional[str]
inputs: Optional[Dict[str, Any]]
type: str = "crew_test_started"
class CrewTestCompleted(CrewEvent):
"""Event emitted when a crew completes testing"""
crew_name: Optional[str]
type: str = "crew_test_completed"
class CrewTestFailed(CrewEvent):
"""Event emitted when a crew fails to complete testing"""
error: str
type: str = "crew_test_failed"

View File

@@ -0,0 +1,99 @@
import threading
from contextlib import contextmanager
from typing import Any, Callable, Dict, List, Type
from blinker import Signal
from .event_types import EventTypes
class EventBus:
"""
A singleton event bus that uses blinker signals for event handling.
Allows both internal (Flow/Crew) and external event handling.
"""
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None: # prevent race condition
cls._instance = super(EventBus, cls).__new__(cls)
cls._instance._initialize()
return cls._instance
def _initialize(self):
"""Initialize the event bus internal state"""
self._signal = Signal("event_bus")
self._handlers: Dict[Type[EventTypes], List[Callable]] = {}
def on(self, event_type: Type[EventTypes]) -> Callable:
"""
Decorator to register an event handler for a specific event type.
Usage:
@event_bus.on(CrewKickoffStarted)
def handle_kickoff(source, event):
print(f"Crew kickoff started: {event}")
"""
def decorator(handler: Callable[[Any, EventTypes], None]):
if event_type not in self._handlers:
self._handlers[event_type] = []
self._handlers[event_type].append(handler)
return handler
return decorator
def emit(self, source: Any, event: EventTypes) -> None:
"""
Emit an event to all registered handlers
Args:
source: The object emitting the event
event: The event instance to emit
"""
event_type = type(event)
if event_type in self._handlers:
for handler in self._handlers[event_type]:
handler(source, event)
self._signal.send(source, event=event)
def clear_handlers(self) -> None:
"""Clear all registered event handlers - useful for testing"""
self._handlers.clear()
def register_handler(
self, event_type: Type[EventTypes], handler: Callable[[Any, EventTypes], None]
) -> None:
"""Register an event handler for a specific event type"""
if event_type not in self._handlers:
self._handlers[event_type] = []
self._handlers[event_type].append(handler)
@contextmanager
def scoped_handlers(self):
"""
Context manager for temporary event handling scope.
Useful for testing or temporary event handling.
Usage:
with event_bus.scoped_handlers():
@event_bus.on(CrewKickoffStarted)
def temp_handler(source, event):
print("Temporary handler")
# Do stuff...
# Handlers are cleared after the context
"""
previous_handlers = self._handlers.copy()
self._handlers.clear()
try:
yield
finally:
self._handlers = previous_handlers
# Global instance
event_bus = EventBus()

View File

@@ -0,0 +1,101 @@
from crewai.telemetry.telemetry import Telemetry
from crewai.utilities.evaluators.task_evaluator import TaskEvaluator
from .agent_events import (
AgentExecutionCompleted,
AgentExecutionStarted,
)
from .crew_events import (
CrewKickoffCompleted,
CrewKickoffStarted,
CrewTestCompleted,
CrewTestStarted,
)
from .event_bus import EventBus
from .flow_events import (
FlowFinished,
FlowStarted,
MethodExecutionFinished,
MethodExecutionStarted,
)
from .task_events import TaskCompleted, TaskStarted
class EventListener:
_telemetry = Telemetry()
def __init__(self):
print("Initializing EventListener")
self._setup_listeners()
self._telemetry.set_tracer()
def _setup_listeners(self):
event_bus = EventBus()
@event_bus.on(CrewKickoffStarted)
def on_crew_started(source, event):
print(f"🚀 Crew '{event.crew_name}' started", event.timestamp)
print("event.inputs", event.inputs)
self._telemetry.crew_execution_span(source, event.inputs)
@event_bus.on(CrewKickoffCompleted)
def on_crew_completed(source, event):
final_string_output = event.output.raw
self._telemetry.end_crew(source, final_string_output)
@event_bus.on(CrewTestStarted)
def on_crew_test_started(source, event):
cloned_crew = source.copy()
cloned_crew._telemetry.test_execution_span(
cloned_crew,
event.n_iterations,
event.inputs,
event.openai_model_name,
)
print(f"🚀 Crew '{event.crew_name}' started test")
@event_bus.on(CrewTestCompleted)
def on_crew_test_completed(source, event):
print(f"👍 Crew '{event.crew_name}' completed test")
@event_bus.on(TaskStarted)
def on_task_started(source, event):
print(f"📋 Task started: {event.task.description}")
@event_bus.on(TaskCompleted)
def on_task_completed(source, event):
print(f"✓ Task completed: {event.task.description}")
print(f" Output: {event.output}")
result = TaskEvaluator(event.task.agent).evaluate(event.task, event.output)
print(f" Evaluation: {result.quality}")
if result.quality > 5:
print(f" ✅ Passed: {result.suggestions}")
else:
print(f" ❌ Failed: {result.suggestions}")
@event_bus.on(AgentExecutionStarted)
def on_agent_execution_started(source, event):
print(
f"🤖 Agent '{event.agent.role}' started task: {event.task.description}"
)
@event_bus.on(AgentExecutionCompleted)
def on_agent_execution_completed(source, event):
print(f"👍 Agent '{event.agent.role}' completed task")
print(f" Output: {event.output}")
@event_bus.on(FlowStarted)
def on_flow_started(source, event):
print(f"🤖 Flow Started: '{event.flow_name}'")
@event_bus.on(FlowFinished)
def on_flow_finished(source, event):
print(f"👍 Flow Finished: '{event.flow_name}'")
@event_bus.on(MethodExecutionStarted)
def on_method_execution_started(source, event):
print(f"🤖 Flow Method Started: '{event.method_name}'")
@event_bus.on(MethodExecutionFinished)
def on_method_execution_finished(source, event):
print(f"👍 Flow Method Finished: '{event.method_name}'")

View File

@@ -0,0 +1,47 @@
from typing import Union
from .agent_events import (
AgentExecutionCompleted,
AgentExecutionStarted,
)
from .crew_events import (
CrewKickoffCompleted,
CrewKickoffFailed,
CrewKickoffStarted,
CrewTestCompleted,
CrewTestFailed,
CrewTestStarted,
CrewTrainCompleted,
CrewTrainFailed,
CrewTrainStarted,
)
from .flow_events import (
FlowFinished,
FlowStarted,
MethodExecutionFinished,
MethodExecutionStarted,
)
from .task_events import (
TaskCompleted,
TaskStarted,
)
EventTypes = Union[
CrewKickoffStarted,
CrewKickoffCompleted,
CrewKickoffFailed,
CrewTestStarted,
CrewTestCompleted,
CrewTestFailed,
CrewTrainStarted,
CrewTrainCompleted,
CrewTrainFailed,
AgentExecutionStarted,
AgentExecutionCompleted,
TaskStarted,
TaskCompleted,
FlowStarted,
FlowFinished,
MethodExecutionStarted,
MethodExecutionFinished,
]

View File

@@ -1,7 +1,19 @@
from functools import wraps
from typing import Any, Callable, Dict, Generic, List, Type, TypeVar
from typing import (
Any,
Callable,
Dict,
Generic,
List,
Type,
TypeVar,
TYPE_CHECKING,
)
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
from pydantic import BaseModel, Field
from .event_types import EventTypes
T = TypeVar("T")
EVT = TypeVar("EVT", bound=BaseModel)
@@ -27,18 +39,15 @@ class Emitter(Generic[T, EVT]):
func(source, event)
# Global event emitter instance
default_emitter = Emitter[Any, BaseModel]()
def emit(source: Any, event: BaseModel, raise_on_error: bool = False) -> None:
try:
default_emitter.emit(source, event)
except Exception as e:
if raise_on_error:
raise e
else:
print(f"Error emitting event: {e}")
def emit(source: Any, event: BaseModel) -> None:
"""Emit an event to all registered listeners"""
default_emitter.emit(source, event)
def on(event_type: Type[BaseModel]) -> Callable:
def on(event_type: Type[EventTypes]) -> Callable:
"""Register a listener for a specific event type"""
return default_emitter.on(event_type)

View File

@@ -0,0 +1,34 @@
from typing import Any, Dict, Optional
from .crew_events import CrewEvent
class FlowStarted(CrewEvent):
"""Event emitted when a flow starts execution"""
flow_name: str
type: str = "flow_started"
class MethodExecutionStarted(CrewEvent):
"""Event emitted when a flow method starts execution"""
flow_name: str
method_name: str
type: str = "method_execution_started"
class MethodExecutionFinished(CrewEvent):
"""Event emitted when a flow method completes execution"""
flow_name: str
method_name: str
type: str = "method_execution_finished"
class FlowFinished(CrewEvent):
"""Event emitted when a flow completes execution"""
flow_name: str
result: Optional[Any] = None
type: str = "flow_finished"

View File

@@ -0,0 +1,22 @@
from typing import Any
from crewai.utilities.events.crew_events import CrewEvent
class TaskStarted(CrewEvent):
"""Event emitted when a task starts"""
task: Any
type: str = "task_started"
model_config = {"arbitrary_types_allowed": True}
class TaskCompleted(CrewEvent):
"""Event emitted when a task completes"""
task: Any
output: Any
type: str = "task_completed"
model_config = {"arbitrary_types_allowed": True}

View File

@@ -0,0 +1,230 @@
interactions:
- request:
body: !!binary |
Cp0mCiQKIgoMc2VydmljZS5uYW1lEhIKEGNyZXdBSS10ZWxlbWV0cnkS9CUKEgoQY3Jld2FpLnRl
bGVtZXRyeRKkBwoQsRaqiDfyxK42TccQwJG7SRII4z1RDvMH0b0qDENyZXcgQ3JlYXRlZDABOdiW
FcGxJCEYQXB3JMGxJCEYShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjBKGgoOcHl0aG9uX3Zl
cnNpb24SCAoGMy4xMi44Si4KCGNyZXdfa2V5EiIKIGU1ODA3MDFkNTJlYjY1YWZmMjRlZWZlNzhj
NzQ2MjhjSjEKB2NyZXdfaWQSJgokN2UyNDlhZmMtZDlkYS00OTVmLWE4NGItMjI0MWFkY2U3ZGVi
ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3
X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrRAgoLY3Jl
d19hZ2VudHMSwQIKvgJbeyJrZXkiOiAiYWQxNTMxNjFjNWM1YTg1NmFhMGQwNmIyNDljNGM2NGEi
LCAiaWQiOiAiMjI4ZWZlMTYtZjEwMC00ZjA0LTllYzItMDQxNTc2ZDMwODNmIiwgInJvbGUiOiAi
YmFzZV9hZ2VudCIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0i
OiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIs
ICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBm
YWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K/wEKCmNyZXdf
dGFza3MS8AEK7QFbeyJrZXkiOiAiMWIxNWVmMjM5MTViMjc1NWU4OWEwZWMzYjI2YTEzZDIiLCAi
aWQiOiAiMzNiM2YxYTktODM5Yy00YzgxLWFkOTgtNjFiYzMzMzljM2Y2IiwgImFzeW5jX2V4ZWN1
dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJiYXNl
X2FnZW50IiwgImFnZW50X2tleSI6ICJhZDE1MzE2MWM1YzVhODU2YWEwZDA2YjI0OWM0YzY0YSIs
ICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChC7VQnwwfAXyqbifjiX/Q9QEghiZojr
aZisPioMVGFzayBDcmVhdGVkMAE56HQ2wbEkIRhBeNo2wbEkIRhKLgoIY3Jld19rZXkSIgogZTU4
MDcwMWQ1MmViNjVhZmYyNGVlZmU3OGM3NDYyOGNKMQoHY3Jld19pZBImCiQ3ZTI0OWFmYy1kOWRh
LTQ5NWYtYTg0Yi0yMjQxYWRjZTdkZWJKLgoIdGFza19rZXkSIgogMWIxNWVmMjM5MTViMjc1NWU4
OWEwZWMzYjI2YTEzZDJKMQoHdGFza19pZBImCiQzM2IzZjFhOS04MzljLTRjODEtYWQ5OC02MWJj
MzMzOWMzZjZ6AhgBhQEAAQAAEqQHChAtKhMjNUrbCPSzpZno1kdhEgg4MmdqKqFAXSoMQ3JldyBD
cmVhdGVkMAE5SBC4xrEkIRhBmIXFxrEkIRhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4xMDAuMEoa
Cg5weXRob25fdmVyc2lvbhIICgYzLjEyLjhKLgoIY3Jld19rZXkSIgogZTU4MDcwMWQ1MmViNjVh
ZmYyNGVlZmU3OGM3NDYyOGNKMQoHY3Jld19pZBImCiQxNzg4Yjg4MC05NzhhLTQzMmMtYTViYi05
ZmY0ZjkxNGMwMWVKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkS
AhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMS
AhgBStECCgtjcmV3X2FnZW50cxLBAgq+Alt7ImtleSI6ICJhZDE1MzE2MWM1YzVhODU2YWEwZDA2
YjI0OWM0YzY0YSIsICJpZCI6ICIyMjhlZmUxNi1mMTAwLTRmMDQtOWVjMi0wNDE1NzZkMzA4M2Yi
LCAicm9sZSI6ICJiYXNlX2FnZW50IiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIw
LCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdw
dC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhl
Y3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119
XUr/AQoKY3Jld190YXNrcxLwAQrtAVt7ImtleSI6ICIxYjE1ZWYyMzkxNWIyNzU1ZTg5YTBlYzNi
MjZhMTNkMiIsICJpZCI6ICIzM2IzZjFhOS04MzljLTRjODEtYWQ5OC02MWJjMzMzOWMzZjYiLCAi
YXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9y
b2xlIjogImJhc2VfYWdlbnQiLCAiYWdlbnRfa2V5IjogImFkMTUzMTYxYzVjNWE4NTZhYTBkMDZi
MjQ5YzRjNjRhIiwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEFPj8mjm/h4Yp972
93VhBIcSCC4p9zkalotLKgxUYXNrIENyZWF0ZWQwATlQ6eDGsSQhGEGogeHGsSQhGEouCghjcmV3
X2tleRIiCiBlNTgwNzAxZDUyZWI2NWFmZjI0ZWVmZTc4Yzc0NjI4Y0oxCgdjcmV3X2lkEiYKJDE3
ODhiODgwLTk3OGEtNDMyYy1hNWJiLTlmZjRmOTE0YzAxZUouCgh0YXNrX2tleRIiCiAxYjE1ZWYy
MzkxNWIyNzU1ZTg5YTBlYzNiMjZhMTNkMkoxCgd0YXNrX2lkEiYKJDMzYjNmMWE5LTgzOWMtNGM4
MS1hZDk4LTYxYmMzMzM5YzNmNnoCGAGFAQABAAASpAcKEM7q3Vt0B41b8yIp9m3apr8SCNFRy5YU
USxvKgxDcmV3IENyZWF0ZWQwATnwwfjHsSQhGEE4dAPIsSQhGEobCg5jcmV3YWlfdmVyc2lvbhIJ
CgcwLjEwMC4wShoKDnB5dGhvbl92ZXJzaW9uEggKBjMuMTIuOEouCghjcmV3X2tleRIiCiBlNTgw
NzAxZDUyZWI2NWFmZjI0ZWVmZTc4Yzc0NjI4Y0oxCgdjcmV3X2lkEiYKJDQyYWExMjM2LTAyZmIt
NGU2MS1hMmYwLTMzOTQwZDUzNTljM0ocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtj
cmV3X21lbW9yeRICEABKGgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVy
X29mX2FnZW50cxICGAFK0QIKC2NyZXdfYWdlbnRzEsECCr4CW3sia2V5IjogImFkMTUzMTYxYzVj
NWE4NTZhYTBkMDZiMjQ5YzRjNjRhIiwgImlkIjogIjIyOGVmZTE2LWYxMDAtNGYwNC05ZWMyLTA0
MTU3NmQzMDgzZiIsICJyb2xlIjogImJhc2VfYWdlbnQiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1h
eF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIs
ICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxs
b3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNf
bmFtZXMiOiBbXX1dSv8BCgpjcmV3X3Rhc2tzEvABCu0BW3sia2V5IjogIjFiMTVlZjIzOTE1YjI3
NTVlODlhMGVjM2IyNmExM2QyIiwgImlkIjogIjMzYjNmMWE5LTgzOWMtNGM4MS1hZDk4LTYxYmMz
MzM5YzNmNiIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxz
ZSwgImFnZW50X3JvbGUiOiAiYmFzZV9hZ2VudCIsICJhZ2VudF9rZXkiOiAiYWQxNTMxNjFjNWM1
YTg1NmFhMGQwNmIyNDljNGM2NGEiLCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQ
Gm3H7iAWI9H+2713+jzGiBIIZtKcjlj6IXgqDFRhc2sgQ3JlYXRlZDABOahOIsixJCEYQXD+Isix
JCEYSi4KCGNyZXdfa2V5EiIKIGU1ODA3MDFkNTJlYjY1YWZmMjRlZWZlNzhjNzQ2MjhjSjEKB2Ny
ZXdfaWQSJgokNDJhYTEyMzYtMDJmYi00ZTYxLWEyZjAtMzM5NDBkNTM1OWMzSi4KCHRhc2tfa2V5
EiIKIDFiMTVlZjIzOTE1YjI3NTVlODlhMGVjM2IyNmExM2QySjEKB3Rhc2tfaWQSJgokMzNiM2Yx
YTktODM5Yy00YzgxLWFkOTgtNjFiYzMzMzljM2Y2egIYAYUBAAEAABKkBwoQXRdWLcLxR1WXiLgw
RBPKChIIvt3M2oEaowsqDENyZXcgQ3JlYXRlZDABOXgVEsmxJCEYQUAAHsmxJCEYShsKDmNyZXdh
aV92ZXJzaW9uEgkKBzAuMTAwLjBKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4xMi44Si4KCGNyZXdf
a2V5EiIKIGU1ODA3MDFkNTJlYjY1YWZmMjRlZWZlNzhjNzQ2MjhjSjEKB2NyZXdfaWQSJgokMGFl
NTlkZWQtMTg0Yy00OGNiLWE2NTktNDljYjQ5OTE4NmMyShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1
ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoV
Y3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrRAgoLY3Jld19hZ2VudHMSwQIKvgJbeyJrZXkiOiAi
YWQxNTMxNjFjNWM1YTg1NmFhMGQwNmIyNDljNGM2NGEiLCAiaWQiOiAiMjI4ZWZlMTYtZjEwMC00
ZjA0LTllYzItMDQxNTc2ZDMwODNmIiwgInJvbGUiOiAiYmFzZV9hZ2VudCIsICJ2ZXJib3NlPyI6
IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGlu
Z19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/Ijog
ZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6
IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K/wEKCmNyZXdfdGFza3MS8AEK7QFbeyJrZXkiOiAiMWIx
NWVmMjM5MTViMjc1NWU4OWEwZWMzYjI2YTEzZDIiLCAiaWQiOiAiMzNiM2YxYTktODM5Yy00Yzgx
LWFkOTgtNjFiYzMzMzljM2Y2IiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lu
cHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJiYXNlX2FnZW50IiwgImFnZW50X2tleSI6ICJh
ZDE1MzE2MWM1YzVhODU2YWEwZDA2YjI0OWM0YzY0YSIsICJ0b29sc19uYW1lcyI6IFtdfV16AhgB
hQEAAQAAEo4CChDKds56rQdRT8dQWNa+o3W8Egigg8CiorCTbSoMVGFzayBDcmVhdGVkMAE5IMku
ybEkIRhBIEYvybEkIRhKLgoIY3Jld19rZXkSIgogZTU4MDcwMWQ1MmViNjVhZmYyNGVlZmU3OGM3
NDYyOGNKMQoHY3Jld19pZBImCiQwYWU1OWRlZC0xODRjLTQ4Y2ItYTY1OS00OWNiNDk5MTg2YzJK
LgoIdGFza19rZXkSIgogMWIxNWVmMjM5MTViMjc1NWU4OWEwZWMzYjI2YTEzZDJKMQoHdGFza19p
ZBImCiQzM2IzZjFhOS04MzljLTRjODEtYWQ5OC02MWJjMzMzOWMzZjZ6AhgBhQEAAQAA
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '4896'
Content-Type:
- application/x-protobuf
User-Agent:
- OTel-OTLP-Exporter-Python/1.27.0
method: POST
uri: https://telemetry.crewai.com:4319/v1/traces
response:
body:
string: "\n\0"
headers:
Content-Length:
- '2'
Content-Type:
- application/x-protobuf
Date:
- Tue, 04 Feb 2025 23:21:22 GMT
status:
code: 200
message: OK
- request:
body: '{"messages": [{"role": "system", "content": "You are failing_agent. You
are an agent that will fail\nYour personal goal is: Fail execution\nTo give
my best complete final answer to the task respond using the exact following
format:\n\nThought: I now can give a great answer\nFinal Answer: Your final
answer must be the great and the most complete as possible, it must be outcome
described.\n\nI MUST use these formats, my job depends on it!"}, {"role": "user",
"content": "\nCurrent Task: This will fail\n\nThis is the expect criteria for
your final answer: hi\nyou MUST return the actual complete content as the final
answer, not a summary.\n\nBegin! This is VERY important to you, use the tools
available and give your best Final Answer, your job depends on it!\n\nThought:"}],
"model": "gpt-4o-mini", "stop": ["\nObservation:"]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '831'
content-type:
- application/json
cookie:
- _cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxMWEsVzvCdMy7AcEMz0E1bIsZE0N\",\n \"object\":
\"chat.completion\",\n \"created\": 1738711278,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
Answer: hi\",\n \"refusal\": null\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
158,\n \"completion_tokens\": 12,\n \"total_tokens\": 170,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
headers:
CF-RAY:
- 90ce656b29f31726-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 23:21:23 GMT
Server:
- cloudflare
Set-Cookie:
- __cf_bm=EdoOe3Ie16YFhyq0JMG_D28BpfQRp_kw01d0usxe.4I-1738711283-1.0.1.1-_S91JqcT20T_.dkcf3nGz_8EvOultyOqoshsb1sa2ovKyLsNvktLklUhWKhcOsCRP7QjoUV.7fah2qCmS1cIbQ;
path=/; expires=Tue, 04-Feb-25 23:51:23 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '5144'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999810'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_40f9e17937c2aa2f80e75dd6c546aeac
http_version: HTTP/1.1
status_code: 200
version: 1

View File

@@ -0,0 +1,315 @@
interactions:
- request:
body: '{"messages": [{"role": "system", "content": "You are base_agent. You are
a helpful assistant that just says hi\nYour personal goal is: Just say hi\nTo
give my best complete final answer to the task respond using the exact following
format:\n\nThought: I now can give a great answer\nFinal Answer: Your final
answer must be the great and the most complete as possible, it must be outcome
described.\n\nI MUST use these formats, my job depends on it!"}, {"role": "user",
"content": "\nCurrent Task: Just say hi\n\nThis is the expect criteria for your
final answer: hi\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nBegin! This is VERY important to you, use the tools available
and give your best Final Answer, your job depends on it!\n\nThought:"}], "model":
"gpt-4o-mini", "stop": ["\nObservation:"]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '836'
content-type:
- application/json
cookie:
- __cf_bm=4s6sWmJ49B9F_wNc1STtdZF1nikfl6uN9_ov3Xzfa8U-1738698987-1.0.1.1-lmbRRS1MHrDbnU93Gh16CP3qNczxxIrQnyBU7vpHSwNf6PdmuWOHKd1mkl5SBx6rg7p1NLaNUMyqDDcE0Mvjzw;
_cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJK2OCJSkUj1plgbj59b4dC39QV2\",\n \"object\":
\"chat.completion\",\n \"created\": 1738698990,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
Answer: hi\",\n \"refusal\": null\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
161,\n \"completion_tokens\": 12,\n \"total_tokens\": 173,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
headers:
CF-RAY:
- 90cd396c0ab71698-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 19:56:30 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '951'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999810'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_2c3cb5caed61ccd1e058ef3e6301c691
http_version: HTTP/1.1
status_code: 200
- request:
body: !!binary |
Cq0TCiQKIgoMc2VydmljZS5uYW1lEhIKEGNyZXdBSS10ZWxlbWV0cnkShBMKEgoQY3Jld2FpLnRl
bGVtZXRyeRKkBwoQzBQBWCz+GLuI1awj3OPWrRIIGpT16t5bk6MqDENyZXcgQ3JlYXRlZDABOUBz
OyuEGSEYQYDBSCuEGSEYShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjBKGgoOcHl0aG9uX3Zl
cnNpb24SCAoGMy4xMi44Si4KCGNyZXdfa2V5EiIKIGU1ODA3MDFkNTJlYjY1YWZmMjRlZWZlNzhj
NzQ2MjhjSjEKB2NyZXdfaWQSJgokMDE3NjQ5ZWMtYTBlMS00MzYxLWFlNjgtYzA1N2E3ZGM5YzI5
ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3
X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrRAgoLY3Jl
d19hZ2VudHMSwQIKvgJbeyJrZXkiOiAiYWQxNTMxNjFjNWM1YTg1NmFhMGQwNmIyNDljNGM2NGEi
LCAiaWQiOiAiOGU3NzgyN2QtN2Y2OC00ZDA2LWI2YTctOWI4YjRkMGE0YzMzIiwgInJvbGUiOiAi
YmFzZV9hZ2VudCIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0i
OiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIs
ICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBm
YWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K/wEKCmNyZXdf
dGFza3MS8AEK7QFbeyJrZXkiOiAiMWIxNWVmMjM5MTViMjc1NWU4OWEwZWMzYjI2YTEzZDIiLCAi
aWQiOiAiOTJiZDIzMWYtYzAxMC00ZDI3LWIxNGYtZjE5NjEyZTBmZTkzIiwgImFzeW5jX2V4ZWN1
dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJiYXNl
X2FnZW50IiwgImFnZW50X2tleSI6ICJhZDE1MzE2MWM1YzVhODU2YWEwZDA2YjI0OWM0YzY0YSIs
ICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChC22Au0eMkAAjV6cfU1NrNIEggxb1Bq
Xnll/ioMVGFzayBDcmVhdGVkMAE5IOJaK4QZIRhBwG5bK4QZIRhKLgoIY3Jld19rZXkSIgogZTU4
MDcwMWQ1MmViNjVhZmYyNGVlZmU3OGM3NDYyOGNKMQoHY3Jld19pZBImCiQwMTc2NDllYy1hMGUx
LTQzNjEtYWU2OC1jMDU3YTdkYzljMjlKLgoIdGFza19rZXkSIgogMWIxNWVmMjM5MTViMjc1NWU4
OWEwZWMzYjI2YTEzZDJKMQoHdGFza19pZBImCiQ5MmJkMjMxZi1jMDEwLTRkMjctYjE0Zi1mMTk2
MTJlMGZlOTN6AhgBhQEAAQAAEqQHChC63jCLGR8RP8RmYiHrdNVeEggZ39ffmGm5xyoMQ3JldyBD
cmVhdGVkMAE5GFEe04QZIRhBELEq04QZIRhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4xMDAuMEoa
Cg5weXRob25fdmVyc2lvbhIICgYzLjEyLjhKLgoIY3Jld19rZXkSIgogZTU4MDcwMWQ1MmViNjVh
ZmYyNGVlZmU3OGM3NDYyOGNKMQoHY3Jld19pZBImCiQ5MTY4YmQxNC0yN2Q2LTQ3NWMtODljOC01
NjJjOTAyMGIxOTBKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkS
AhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMS
AhgBStECCgtjcmV3X2FnZW50cxLBAgq+Alt7ImtleSI6ICJhZDE1MzE2MWM1YzVhODU2YWEwZDA2
YjI0OWM0YzY0YSIsICJpZCI6ICI4ZTc3ODI3ZC03ZjY4LTRkMDYtYjZhNy05YjhiNGQwYTRjMzMi
LCAicm9sZSI6ICJiYXNlX2FnZW50IiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIw
LCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdw
dC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhl
Y3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119
XUr/AQoKY3Jld190YXNrcxLwAQrtAVt7ImtleSI6ICIxYjE1ZWYyMzkxNWIyNzU1ZTg5YTBlYzNi
MjZhMTNkMiIsICJpZCI6ICI5MmJkMjMxZi1jMDEwLTRkMjctYjE0Zi1mMTk2MTJlMGZlOTMiLCAi
YXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9y
b2xlIjogImJhc2VfYWdlbnQiLCAiYWdlbnRfa2V5IjogImFkMTUzMTYxYzVjNWE4NTZhYTBkMDZi
MjQ5YzRjNjRhIiwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEOo6FGs7r9hHrN+f
qhMTUysSCJgbYV+vQMbCKgxUYXNrIENyZWF0ZWQwATlAxjrThBkhGEEYIDvThBkhGEouCghjcmV3
X2tleRIiCiBlNTgwNzAxZDUyZWI2NWFmZjI0ZWVmZTc4Yzc0NjI4Y0oxCgdjcmV3X2lkEiYKJDkx
NjhiZDE0LTI3ZDYtNDc1Yy04OWM4LTU2MmM5MDIwYjE5MEouCgh0YXNrX2tleRIiCiAxYjE1ZWYy
MzkxNWIyNzU1ZTg5YTBlYzNiMjZhMTNkMkoxCgd0YXNrX2lkEiYKJDkyYmQyMzFmLWMwMTAtNGQy
Ny1iMTRmLWYxOTYxMmUwZmU5M3oCGAGFAQABAAA=
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '2480'
Content-Type:
- application/x-protobuf
User-Agent:
- OTel-OTLP-Exporter-Python/1.27.0
method: POST
uri: https://telemetry.crewai.com:4319/v1/traces
response:
body:
string: "\n\0"
headers:
Content-Length:
- '2'
Content-Type:
- application/x-protobuf
Date:
- Tue, 04 Feb 2025 19:56:31 GMT
status:
code: 200
message: OK
- request:
body: '{"messages": [{"role": "user", "content": "Assess the quality of the task
completed based on the description, expected output, and actual results.\n\nTask
Description:\nJust say hi\n\nExpected Output:\nhi\n\nActual Output:\nhi\n\nPlease
provide:\n- Bullet points suggestions to improve future similar tasks\n- A score
from 0 to 10 evaluating on completion, quality, and overall performance- Entities
extracted from the task output, if any, their type, description, and relationships"}],
"model": "gpt-4o-mini", "tool_choice": {"type": "function", "function": {"name":
"TaskEvaluation"}}, "tools": [{"type": "function", "function": {"name": "TaskEvaluation",
"description": "Correctly extracted `TaskEvaluation` with all the required parameters
with correct types", "parameters": {"$defs": {"Entity": {"properties": {"name":
{"description": "The name of the entity.", "title": "Name", "type": "string"},
"type": {"description": "The type of the entity.", "title": "Type", "type":
"string"}, "description": {"description": "Description of the entity.", "title":
"Description", "type": "string"}, "relationships": {"description": "Relationships
of the entity.", "items": {"type": "string"}, "title": "Relationships", "type":
"array"}}, "required": ["name", "type", "description", "relationships"], "title":
"Entity", "type": "object"}}, "properties": {"suggestions": {"description":
"Suggestions to improve future similar tasks.", "items": {"type": "string"},
"title": "Suggestions", "type": "array"}, "quality": {"description": "A score
from 0 to 10 evaluating on completion, quality, and overall performance, all
taking into account the task description, expected output, and the result of
the task.", "title": "Quality", "type": "number"}, "entities": {"description":
"Entities extracted from the task output.", "items": {"$ref": "#/$defs/Entity"},
"title": "Entities", "type": "array"}}, "required": ["entities", "quality",
"suggestions"], "type": "object"}}}]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '1962'
content-type:
- application/json
cookie:
- __cf_bm=4s6sWmJ49B9F_wNc1STtdZF1nikfl6uN9_ov3Xzfa8U-1738698987-1.0.1.1-lmbRRS1MHrDbnU93Gh16CP3qNczxxIrQnyBU7vpHSwNf6PdmuWOHKd1mkl5SBx6rg7p1NLaNUMyqDDcE0Mvjzw;
_cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJK3bJiyqGhPeqdCcCjoeNavGHrR\",\n \"object\":
\"chat.completion\",\n \"created\": 1738698991,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_uAFkclWHIRqgrXFrQFcEoUIS\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"TaskEvaluation\",\n
\ \"arguments\": \"{\\\"suggestions\\\":[\\\"Include additional
context for the greeting to make it more meaningful.\\\",\\\"Specify if you
want a casual or formal tone for greetings.\\\",\\\"Provide examples of variations
of the greeting if necessary.\\\"],\\\"quality\\\":10,\\\"entities\\\":[],\\\"relationships\\\":[]}\"\n
\ }\n }\n ],\n \"refusal\": null\n },\n
\ \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n ],\n
\ \"usage\": {\n \"prompt_tokens\": 273,\n \"completion_tokens\": 50,\n
\ \"total_tokens\": 323,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_bd83329f63\"\n}\n"
headers:
CF-RAY:
- 90cd3973589f1698-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 19:56:32 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '1408'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999876'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_519fd27ca3d5da4d541c4331654e0520
http_version: HTTP/1.1
status_code: 200
version: 1

View File

@@ -0,0 +1,357 @@
interactions:
- request:
body: '{"messages": [{"role": "system", "content": "You are base_agent. You are
a helpful assistant that just says hi\nYour personal goal is: Just say hi\nTo
give my best complete final answer to the task respond using the exact following
format:\n\nThought: I now can give a great answer\nFinal Answer: Your final
answer must be the great and the most complete as possible, it must be outcome
described.\n\nI MUST use these formats, my job depends on it!"}, {"role": "user",
"content": "\nCurrent Task: Just say hi\n\nThis is the expect criteria for your
final answer: hi\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nBegin! This is VERY important to you, use the tools available
and give your best Final Answer, your job depends on it!\n\nThought:"}], "model":
"gpt-4o-mini", "stop": ["\nObservation:"]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '836'
content-type:
- application/json
cookie:
- __cf_bm=nedOdWE1YnKQYt1kSbrcA.zhwa3bZDzmZqTOjZYER0c-1738700521-1.0.1.1-xQk9iXOvqvyXNhkIOgc8Ws2WYcT1mJFkDCvCC8xA5joFD8QfNrBIAr_Qs6sIxt2EzXyeFwBA6gA8ZgWApCHx0Q;
_cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJlK2np8dMxYgsDIuyz2TSKKELWh\",\n \"object\":
\"chat.completion\",\n \"created\": 1738700682,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
Answer: hi\",\n \"refusal\": null\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
161,\n \"completion_tokens\": 12,\n \"total_tokens\": 173,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
headers:
CF-RAY:
- 90cd62c1fdb0fa6a-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 20:24:42 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '326'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999810'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_22be86be6fd9d69ca8d310ef534e7bec
http_version: HTTP/1.1
status_code: 200
- request:
body: !!binary |
Cp0mCiQKIgoMc2VydmljZS5uYW1lEhIKEGNyZXdBSS10ZWxlbWV0cnkS9CUKEgoQY3Jld2FpLnRl
bGVtZXRyeRKkBwoQfRmsiIy66Scw43CcUw5ZiBIIfYDEhWJTOTkqDENyZXcgQ3JlYXRlZDABOcD6
XvsOGyEYQWC2bPsOGyEYShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjBKGgoOcHl0aG9uX3Zl
cnNpb24SCAoGMy4xMi44Si4KCGNyZXdfa2V5EiIKIGU1ODA3MDFkNTJlYjY1YWZmMjRlZWZlNzhj
NzQ2MjhjSjEKB2NyZXdfaWQSJgokMDMzNTZiYmEtMzJmZC00OThmLTgxYTItYzc1ZDBkMzc2N2Qx
ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3
X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrRAgoLY3Jl
d19hZ2VudHMSwQIKvgJbeyJrZXkiOiAiYWQxNTMxNjFjNWM1YTg1NmFhMGQwNmIyNDljNGM2NGEi
LCAiaWQiOiAiZjY5YTRmYTMtMzQ4OC00MmFhLTlhMTQtMGEzZmEyOWJmYjZjIiwgInJvbGUiOiAi
YmFzZV9hZ2VudCIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0i
OiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIs
ICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBm
YWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K/wEKCmNyZXdf
dGFza3MS8AEK7QFbeyJrZXkiOiAiMWIxNWVmMjM5MTViMjc1NWU4OWEwZWMzYjI2YTEzZDIiLCAi
aWQiOiAiNDllNzk0MmMtZTJiMy00YmE1LTg5MTUtMTYwYjQxMDU2ZmVlIiwgImFzeW5jX2V4ZWN1
dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJiYXNl
X2FnZW50IiwgImFnZW50X2tleSI6ICJhZDE1MzE2MWM1YzVhODU2YWEwZDA2YjI0OWM0YzY0YSIs
ICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChCLgjutPq/3tkNyPqVjfbZhEgjhB7lb
clxzdyoMVGFzayBDcmVhdGVkMAE5CC9++w4bIRhBeMN++w4bIRhKLgoIY3Jld19rZXkSIgogZTU4
MDcwMWQ1MmViNjVhZmYyNGVlZmU3OGM3NDYyOGNKMQoHY3Jld19pZBImCiQwMzM1NmJiYS0zMmZk
LTQ5OGYtODFhMi1jNzVkMGQzNzY3ZDFKLgoIdGFza19rZXkSIgogMWIxNWVmMjM5MTViMjc1NWU4
OWEwZWMzYjI2YTEzZDJKMQoHdGFza19pZBImCiQ0OWU3OTQyYy1lMmIzLTRiYTUtODkxNS0xNjBi
NDEwNTZmZWV6AhgBhQEAAQAAEqQHChC7SpRSs6eG9XFmYuMQgghQEghpZMlScOy2DyoMQ3JldyBD
cmVhdGVkMAE50O2cAA8bIRhBOFmrAA8bIRhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4xMDAuMEoa
Cg5weXRob25fdmVyc2lvbhIICgYzLjEyLjhKLgoIY3Jld19rZXkSIgogZTU4MDcwMWQ1MmViNjVh
ZmYyNGVlZmU3OGM3NDYyOGNKMQoHY3Jld19pZBImCiRlYTQ1MWY2OS00Zjk3LTQ4MjYtOWNlYi04
NTAzMDk2MTQ2MDlKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkS
AhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMS
AhgBStECCgtjcmV3X2FnZW50cxLBAgq+Alt7ImtleSI6ICJhZDE1MzE2MWM1YzVhODU2YWEwZDA2
YjI0OWM0YzY0YSIsICJpZCI6ICJmNjlhNGZhMy0zNDg4LTQyYWEtOWExNC0wYTNmYTI5YmZiNmMi
LCAicm9sZSI6ICJiYXNlX2FnZW50IiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIw
LCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdw
dC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhl
Y3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119
XUr/AQoKY3Jld190YXNrcxLwAQrtAVt7ImtleSI6ICIxYjE1ZWYyMzkxNWIyNzU1ZTg5YTBlYzNi
MjZhMTNkMiIsICJpZCI6ICI0OWU3OTQyYy1lMmIzLTRiYTUtODkxNS0xNjBiNDEwNTZmZWUiLCAi
YXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9y
b2xlIjogImJhc2VfYWdlbnQiLCAiYWdlbnRfa2V5IjogImFkMTUzMTYxYzVjNWE4NTZhYTBkMDZi
MjQ5YzRjNjRhIiwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEM1q5zTl6Q6WKHPQ
eIqEm7sSCCWi2wvaFqpfKgxUYXNrIENyZWF0ZWQwATmIObwADxshGEEAo7wADxshGEouCghjcmV3
X2tleRIiCiBlNTgwNzAxZDUyZWI2NWFmZjI0ZWVmZTc4Yzc0NjI4Y0oxCgdjcmV3X2lkEiYKJGVh
NDUxZjY5LTRmOTctNDgyNi05Y2ViLTg1MDMwOTYxNDYwOUouCgh0YXNrX2tleRIiCiAxYjE1ZWYy
MzkxNWIyNzU1ZTg5YTBlYzNiMjZhMTNkMkoxCgd0YXNrX2lkEiYKJDQ5ZTc5NDJjLWUyYjMtNGJh
NS04OTE1LTE2MGI0MTA1NmZlZXoCGAGFAQABAAASpAcKEEhIZzGdZRAdvfcluDR5qvESCFMGo60X
V/dYKgxDcmV3IENyZWF0ZWQwATnY8LgBDxshGEGQrsUBDxshGEobCg5jcmV3YWlfdmVyc2lvbhIJ
CgcwLjEwMC4wShoKDnB5dGhvbl92ZXJzaW9uEggKBjMuMTIuOEouCghjcmV3X2tleRIiCiBlNTgw
NzAxZDUyZWI2NWFmZjI0ZWVmZTc4Yzc0NjI4Y0oxCgdjcmV3X2lkEiYKJDA3MDJmOGU1LWRjMTYt
NDlhYi1hMWY1LThjOWQyY2IwMDYwYkocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtj
cmV3X21lbW9yeRICEABKGgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVy
X29mX2FnZW50cxICGAFK0QIKC2NyZXdfYWdlbnRzEsECCr4CW3sia2V5IjogImFkMTUzMTYxYzVj
NWE4NTZhYTBkMDZiMjQ5YzRjNjRhIiwgImlkIjogImY2OWE0ZmEzLTM0ODgtNDJhYS05YTE0LTBh
M2ZhMjliZmI2YyIsICJyb2xlIjogImJhc2VfYWdlbnQiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1h
eF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIs
ICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxs
b3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNf
bmFtZXMiOiBbXX1dSv8BCgpjcmV3X3Rhc2tzEvABCu0BW3sia2V5IjogIjFiMTVlZjIzOTE1YjI3
NTVlODlhMGVjM2IyNmExM2QyIiwgImlkIjogIjQ5ZTc5NDJjLWUyYjMtNGJhNS04OTE1LTE2MGI0
MTA1NmZlZSIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxz
ZSwgImFnZW50X3JvbGUiOiAiYmFzZV9hZ2VudCIsICJhZ2VudF9rZXkiOiAiYWQxNTMxNjFjNWM1
YTg1NmFhMGQwNmIyNDljNGM2NGEiLCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQ
PkgvMtq3aT5YPXE8gCRxPBIIMx/zQOuC+8sqDFRhc2sgQ3JlYXRlZDABOYjk2AEPGyEYQZiI2QEP
GyEYSi4KCGNyZXdfa2V5EiIKIGU1ODA3MDFkNTJlYjY1YWZmMjRlZWZlNzhjNzQ2MjhjSjEKB2Ny
ZXdfaWQSJgokMDcwMmY4ZTUtZGMxNi00OWFiLWExZjUtOGM5ZDJjYjAwNjBiSi4KCHRhc2tfa2V5
EiIKIDFiMTVlZjIzOTE1YjI3NTVlODlhMGVjM2IyNmExM2QySjEKB3Rhc2tfaWQSJgokNDllNzk0
MmMtZTJiMy00YmE1LTg5MTUtMTYwYjQxMDU2ZmVlegIYAYUBAAEAABKkBwoQex7nA0gUUrZHbN6F
gWp/gBIIKPd4fiRi7DwqDENyZXcgQ3JlYXRlZDABOTiIrAIPGyEYQdCAtwIPGyEYShsKDmNyZXdh
aV92ZXJzaW9uEgkKBzAuMTAwLjBKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4xMi44Si4KCGNyZXdf
a2V5EiIKIGU1ODA3MDFkNTJlYjY1YWZmMjRlZWZlNzhjNzQ2MjhjSjEKB2NyZXdfaWQSJgokMGNm
YjUzZWItMDA2Mi00YmVmLTk1ZTgtMDgwMjQ3NmNkMWRlShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1
ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoV
Y3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrRAgoLY3Jld19hZ2VudHMSwQIKvgJbeyJrZXkiOiAi
YWQxNTMxNjFjNWM1YTg1NmFhMGQwNmIyNDljNGM2NGEiLCAiaWQiOiAiZjY5YTRmYTMtMzQ4OC00
MmFhLTlhMTQtMGEzZmEyOWJmYjZjIiwgInJvbGUiOiAiYmFzZV9hZ2VudCIsICJ2ZXJib3NlPyI6
IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGlu
Z19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/Ijog
ZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6
IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K/wEKCmNyZXdfdGFza3MS8AEK7QFbeyJrZXkiOiAiMWIx
NWVmMjM5MTViMjc1NWU4OWEwZWMzYjI2YTEzZDIiLCAiaWQiOiAiNDllNzk0MmMtZTJiMy00YmE1
LTg5MTUtMTYwYjQxMDU2ZmVlIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lu
cHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJiYXNlX2FnZW50IiwgImFnZW50X2tleSI6ICJh
ZDE1MzE2MWM1YzVhODU2YWEwZDA2YjI0OWM0YzY0YSIsICJ0b29sc19uYW1lcyI6IFtdfV16AhgB
hQEAAQAAEo4CChD+ymllejCksajGYDua8tgNEghnjlejrbuw2SoMVGFzayBDcmVhdGVkMAE5EDrI
Ag8bIRhBGIzIAg8bIRhKLgoIY3Jld19rZXkSIgogZTU4MDcwMWQ1MmViNjVhZmYyNGVlZmU3OGM3
NDYyOGNKMQoHY3Jld19pZBImCiQwY2ZiNTNlYi0wMDYyLTRiZWYtOTVlOC0wODAyNDc2Y2QxZGVK
LgoIdGFza19rZXkSIgogMWIxNWVmMjM5MTViMjc1NWU4OWEwZWMzYjI2YTEzZDJKMQoHdGFza19p
ZBImCiQ0OWU3OTQyYy1lMmIzLTRiYTUtODkxNS0xNjBiNDEwNTZmZWV6AhgBhQEAAQAA
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '4896'
Content-Type:
- application/x-protobuf
User-Agent:
- OTel-OTLP-Exporter-Python/1.27.0
method: POST
uri: https://telemetry.crewai.com:4319/v1/traces
response:
body:
string: "\n\0"
headers:
Content-Length:
- '2'
Content-Type:
- application/x-protobuf
Date:
- Tue, 04 Feb 2025 20:24:47 GMT
status:
code: 200
message: OK
- request:
body: '{"messages": [{"role": "user", "content": "Assess the quality of the task
completed based on the description, expected output, and actual results.\n\nTask
Description:\nJust say hi\n\nExpected Output:\nhi\n\nActual Output:\nhi\n\nPlease
provide:\n- Bullet points suggestions to improve future similar tasks\n- A score
from 0 to 10 evaluating on completion, quality, and overall performance- Entities
extracted from the task output, if any, their type, description, and relationships"}],
"model": "gpt-4o-mini", "tool_choice": {"type": "function", "function": {"name":
"TaskEvaluation"}}, "tools": [{"type": "function", "function": {"name": "TaskEvaluation",
"description": "Correctly extracted `TaskEvaluation` with all the required parameters
with correct types", "parameters": {"$defs": {"Entity": {"properties": {"name":
{"description": "The name of the entity.", "title": "Name", "type": "string"},
"type": {"description": "The type of the entity.", "title": "Type", "type":
"string"}, "description": {"description": "Description of the entity.", "title":
"Description", "type": "string"}, "relationships": {"description": "Relationships
of the entity.", "items": {"type": "string"}, "title": "Relationships", "type":
"array"}}, "required": ["name", "type", "description", "relationships"], "title":
"Entity", "type": "object"}}, "properties": {"suggestions": {"description":
"Suggestions to improve future similar tasks.", "items": {"type": "string"},
"title": "Suggestions", "type": "array"}, "quality": {"description": "A score
from 0 to 10 evaluating on completion, quality, and overall performance, all
taking into account the task description, expected output, and the result of
the task.", "title": "Quality", "type": "number"}, "entities": {"description":
"Entities extracted from the task output.", "items": {"$ref": "#/$defs/Entity"},
"title": "Entities", "type": "array"}}, "required": ["entities", "quality",
"suggestions"], "type": "object"}}}]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '1962'
content-type:
- application/json
cookie:
- __cf_bm=nedOdWE1YnKQYt1kSbrcA.zhwa3bZDzmZqTOjZYER0c-1738700521-1.0.1.1-xQk9iXOvqvyXNhkIOgc8Ws2WYcT1mJFkDCvCC8xA5joFD8QfNrBIAr_Qs6sIxt2EzXyeFwBA6gA8ZgWApCHx0Q;
_cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJlLVC3gCB9gRI0ZSkoPCZY7EwpQ\",\n \"object\":
\"chat.completion\",\n \"created\": 1738700683,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_mgwImOITW8lkjzAyf9Pp76cL\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"TaskEvaluation\",\n
\ \"arguments\": \"{\\\"suggestions\\\":[\\\"Provide context or
additional information to make tasks more engaging.\\\",\\\"Encourage variations
in responses to make the interaction more dynamic.\\\"],\\\"quality\\\":10,\\\"entities\\\":[{\\\"name\\\":\\\"hi\\\",\\\"type\\\":\\\"greeting\\\",\\\"description\\\":\\\"A
common word used to initiate a conversation or express friendliness.\\\",\\\"relationships\\\":[\\\"initiates
conversation\\\",\\\"expresses friendliness\\\"]}]}\"\n }\n }\n
\ ],\n \"refusal\": null\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
273,\n \"completion_tokens\": 71,\n \"total_tokens\": 344,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_bd83329f63\"\n}\n"
headers:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- 90cd62c4ba41fa6a-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 20:24:50 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '7347'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999876'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_aec28dd3fe998d628754e8429623bf9e
http_version: HTTP/1.1
status_code: 200
version: 1

View File

@@ -0,0 +1,245 @@
interactions:
- request:
body: '{"messages": [{"role": "system", "content": "You are base_agent. You are
a helpful assistant that just says hi\nYour personal goal is: Just say hi\nTo
give my best complete final answer to the task respond using the exact following
format:\n\nThought: I now can give a great answer\nFinal Answer: Your final
answer must be the great and the most complete as possible, it must be outcome
described.\n\nI MUST use these formats, my job depends on it!"}, {"role": "user",
"content": "\nCurrent Task: Just say hi\n\nThis is the expect criteria for your
final answer: hi\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nBegin! This is VERY important to you, use the tools available
and give your best Final Answer, your job depends on it!\n\nThought:"}], "model":
"gpt-4o-mini", "stop": ["\nObservation:"]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '836'
content-type:
- application/json
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJIrSWAFqDEsNtLRhcM8vMHO9Ejw\",\n \"object\":
\"chat.completion\",\n \"created\": 1738698917,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
Answer: hi\",\n \"refusal\": null\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
161,\n \"completion_tokens\": 12,\n \"total_tokens\": 173,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
headers:
CF-RAY:
- 90cd37a83f5f176a-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 19:55:18 GMT
Server:
- cloudflare
Set-Cookie:
- __cf_bm=rKQWp4fbAvcCp4rasEN6DqiTjQfiWYpLfjcLpWcmzi0-1738698918-1.0.1.1-qlcCSdBY3KWbzVms0eLtz5ub5SSLGs_sRLxTdNhDk_purQuz9k6EFp8PHJfN3aP_sLnuyKnFlppM3.2k_dCtPQ;
path=/; expires=Tue, 04-Feb-25 20:25:18 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=Oi91zDXvjWohBYXSVqK4hFsq3_GZePEIIbi7b7wrjcI-1738698918130-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '894'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999810'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_864253996bbc0f797f9a2c1b9247a0d5
http_version: HTTP/1.1
status_code: 200
- request:
body: '{"messages": [{"role": "user", "content": "Assess the quality of the task
completed based on the description, expected output, and actual results.\n\nTask
Description:\nJust say hi\n\nExpected Output:\nhi\n\nActual Output:\nhi\n\nPlease
provide:\n- Bullet points suggestions to improve future similar tasks\n- A score
from 0 to 10 evaluating on completion, quality, and overall performance- Entities
extracted from the task output, if any, their type, description, and relationships"}],
"model": "gpt-4o-mini", "tool_choice": {"type": "function", "function": {"name":
"TaskEvaluation"}}, "tools": [{"type": "function", "function": {"name": "TaskEvaluation",
"description": "Correctly extracted `TaskEvaluation` with all the required parameters
with correct types", "parameters": {"$defs": {"Entity": {"properties": {"name":
{"description": "The name of the entity.", "title": "Name", "type": "string"},
"type": {"description": "The type of the entity.", "title": "Type", "type":
"string"}, "description": {"description": "Description of the entity.", "title":
"Description", "type": "string"}, "relationships": {"description": "Relationships
of the entity.", "items": {"type": "string"}, "title": "Relationships", "type":
"array"}}, "required": ["name", "type", "description", "relationships"], "title":
"Entity", "type": "object"}}, "properties": {"suggestions": {"description":
"Suggestions to improve future similar tasks.", "items": {"type": "string"},
"title": "Suggestions", "type": "array"}, "quality": {"description": "A score
from 0 to 10 evaluating on completion, quality, and overall performance, all
taking into account the task description, expected output, and the result of
the task.", "title": "Quality", "type": "number"}, "entities": {"description":
"Entities extracted from the task output.", "items": {"$ref": "#/$defs/Entity"},
"title": "Entities", "type": "array"}}, "required": ["entities", "quality",
"suggestions"], "type": "object"}}}]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '1962'
content-type:
- application/json
cookie:
- __cf_bm=rKQWp4fbAvcCp4rasEN6DqiTjQfiWYpLfjcLpWcmzi0-1738698918-1.0.1.1-qlcCSdBY3KWbzVms0eLtz5ub5SSLGs_sRLxTdNhDk_purQuz9k6EFp8PHJfN3aP_sLnuyKnFlppM3.2k_dCtPQ;
_cfuvid=Oi91zDXvjWohBYXSVqK4hFsq3_GZePEIIbi7b7wrjcI-1738698918130-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJIsVEppA04iGQh0k6sanKnVObrO\",\n \"object\":
\"chat.completion\",\n \"created\": 1738698918,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_AQ3iizjGWjEvk1SmhGCzjbf1\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"TaskEvaluation\",\n
\ \"arguments\": \"{\\\"suggestions\\\":[\\\"Provide context for
the greeting, like a specific scenario or recipient.\\\",\\\"Encourage responses
or follow-ups to promote engagement.\\\",\\\"Specify the tone or formality of
the greeting, if relevant.\\\"],\\\"quality\\\":10,\\\"entities\\\":[{\\\"name\\\":\\\"hi\\\",\\\"type\\\":\\\"greeting\\\",\\\"description\\\":\\\"A
common informal expression used to initiate conversation or acknowledge someone.\\\",\\\"relationships\\\":[\\\"used
in conversation\\\",\\\"expresses friendliness\\\"]}]}\"\n }\n }\n
\ ],\n \"refusal\": null\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
273,\n \"completion_tokens\": 84,\n \"total_tokens\": 357,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_bd83329f63\"\n}\n"
headers:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- 90cd37aec8c8176a-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 19:55:21 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '3269'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999876'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_e6e67a3f5c6f2d48e0351cdce95edd97
http_version: HTTP/1.1
status_code: 200
version: 1

View File

@@ -0,0 +1,243 @@
interactions:
- request:
body: '{"messages": [{"role": "system", "content": "You are base_agent. You are
a helpful assistant that just says hi\nYour personal goal is: Just say hi\nTo
give my best complete final answer to the task respond using the exact following
format:\n\nThought: I now can give a great answer\nFinal Answer: Your final
answer must be the great and the most complete as possible, it must be outcome
described.\n\nI MUST use these formats, my job depends on it!"}, {"role": "user",
"content": "\nCurrent Task: Just say hi\n\nThis is the expect criteria for your
final answer: hi\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nBegin! This is VERY important to you, use the tools available
and give your best Final Answer, your job depends on it!\n\nThought:"}], "model":
"gpt-4o-mini", "stop": ["\nObservation:"]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '836'
content-type:
- application/json
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJJzafmayYpGTsTAWbOyZkmQJNa5\",\n \"object\":
\"chat.completion\",\n \"created\": 1738698987,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
Answer: hi\",\n \"refusal\": null\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
161,\n \"completion_tokens\": 12,\n \"total_tokens\": 173,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
headers:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- 90cd395b0e641698-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 19:56:27 GMT
Server:
- cloudflare
Set-Cookie:
- __cf_bm=4s6sWmJ49B9F_wNc1STtdZF1nikfl6uN9_ov3Xzfa8U-1738698987-1.0.1.1-lmbRRS1MHrDbnU93Gh16CP3qNczxxIrQnyBU7vpHSwNf6PdmuWOHKd1mkl5SBx6rg7p1NLaNUMyqDDcE0Mvjzw;
path=/; expires=Tue, 04-Feb-25 20:26:27 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '839'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999810'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_577b484a927b455c40ed80f9fd4d9106
http_version: HTTP/1.1
status_code: 200
- request:
body: '{"messages": [{"role": "user", "content": "Assess the quality of the task
completed based on the description, expected output, and actual results.\n\nTask
Description:\nJust say hi\n\nExpected Output:\nhi\n\nActual Output:\nhi\n\nPlease
provide:\n- Bullet points suggestions to improve future similar tasks\n- A score
from 0 to 10 evaluating on completion, quality, and overall performance- Entities
extracted from the task output, if any, their type, description, and relationships"}],
"model": "gpt-4o-mini", "tool_choice": {"type": "function", "function": {"name":
"TaskEvaluation"}}, "tools": [{"type": "function", "function": {"name": "TaskEvaluation",
"description": "Correctly extracted `TaskEvaluation` with all the required parameters
with correct types", "parameters": {"$defs": {"Entity": {"properties": {"name":
{"description": "The name of the entity.", "title": "Name", "type": "string"},
"type": {"description": "The type of the entity.", "title": "Type", "type":
"string"}, "description": {"description": "Description of the entity.", "title":
"Description", "type": "string"}, "relationships": {"description": "Relationships
of the entity.", "items": {"type": "string"}, "title": "Relationships", "type":
"array"}}, "required": ["name", "type", "description", "relationships"], "title":
"Entity", "type": "object"}}, "properties": {"suggestions": {"description":
"Suggestions to improve future similar tasks.", "items": {"type": "string"},
"title": "Suggestions", "type": "array"}, "quality": {"description": "A score
from 0 to 10 evaluating on completion, quality, and overall performance, all
taking into account the task description, expected output, and the result of
the task.", "title": "Quality", "type": "number"}, "entities": {"description":
"Entities extracted from the task output.", "items": {"$ref": "#/$defs/Entity"},
"title": "Entities", "type": "array"}}, "required": ["entities", "quality",
"suggestions"], "type": "object"}}}]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '1962'
content-type:
- application/json
cookie:
- __cf_bm=4s6sWmJ49B9F_wNc1STtdZF1nikfl6uN9_ov3Xzfa8U-1738698987-1.0.1.1-lmbRRS1MHrDbnU93Gh16CP3qNczxxIrQnyBU7vpHSwNf6PdmuWOHKd1mkl5SBx6rg7p1NLaNUMyqDDcE0Mvjzw;
_cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJJz10KP7iadNPdKsbcsvHBa7cic\",\n \"object\":
\"chat.completion\",\n \"created\": 1738698987,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_czeHQgy5eiOVa0zlrtcfwepe\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"TaskEvaluation\",\n
\ \"arguments\": \"{\\\"suggestions\\\":[\\\"Provide more context
or details for similar tasks to enhance output expectations.\\\",\\\"Encourage
creativity in responses for simple tasks to engage users more effectively.\\\"],\\\"quality\\\":10,\\\"entities\\\":[]
}\"\n }\n }\n ],\n \"refusal\": null\n },\n
\ \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n ],\n
\ \"usage\": {\n \"prompt_tokens\": 273,\n \"completion_tokens\": 40,\n
\ \"total_tokens\": 313,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_bd83329f63\"\n}\n"
headers:
CF-RAY:
- 90cd39615b281698-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 19:56:29 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '1411'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999876'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_3e717a80c7d9c5ea19893dd990aaae26
http_version: HTTP/1.1
status_code: 200
version: 1

View File

@@ -0,0 +1,245 @@
interactions:
- request:
body: '{"messages": [{"role": "system", "content": "You are base_agent. You are
a helpful assistant that just says hi\nYour personal goal is: Just say hi\nTo
give my best complete final answer to the task respond using the exact following
format:\n\nThought: I now can give a great answer\nFinal Answer: Your final
answer must be the great and the most complete as possible, it must be outcome
described.\n\nI MUST use these formats, my job depends on it!"}, {"role": "user",
"content": "\nCurrent Task: Just say hi\n\nThis is the expect criteria for your
final answer: hi\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nBegin! This is VERY important to you, use the tools available
and give your best Final Answer, your job depends on it!\n\nThought:"}], "model":
"gpt-4o-mini", "stop": ["\nObservation:"]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '836'
content-type:
- application/json
cookie:
- __cf_bm=4s6sWmJ49B9F_wNc1STtdZF1nikfl6uN9_ov3Xzfa8U-1738698987-1.0.1.1-lmbRRS1MHrDbnU93Gh16CP3qNczxxIrQnyBU7vpHSwNf6PdmuWOHKd1mkl5SBx6rg7p1NLaNUMyqDDcE0Mvjzw;
_cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJiiHEQwIXsiG0Sd5wofcuhxVbo9\",\n \"object\":
\"chat.completion\",\n \"created\": 1738700520,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
Answer: hi\",\n \"refusal\": null\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
161,\n \"completion_tokens\": 12,\n \"total_tokens\": 173,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
headers:
CF-RAY:
- 90cd5ecd0f7667ee-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 20:22:01 GMT
Server:
- cloudflare
Set-Cookie:
- __cf_bm=nedOdWE1YnKQYt1kSbrcA.zhwa3bZDzmZqTOjZYER0c-1738700521-1.0.1.1-xQk9iXOvqvyXNhkIOgc8Ws2WYcT1mJFkDCvCC8xA5joFD8QfNrBIAr_Qs6sIxt2EzXyeFwBA6gA8ZgWApCHx0Q;
path=/; expires=Tue, 04-Feb-25 20:52:01 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '450'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999810'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_10eaafc81640a98a0a4789d270dd94d9
http_version: HTTP/1.1
status_code: 200
- request:
body: '{"messages": [{"role": "user", "content": "Assess the quality of the task
completed based on the description, expected output, and actual results.\n\nTask
Description:\nJust say hi\n\nExpected Output:\nhi\n\nActual Output:\nhi\n\nPlease
provide:\n- Bullet points suggestions to improve future similar tasks\n- A score
from 0 to 10 evaluating on completion, quality, and overall performance- Entities
extracted from the task output, if any, their type, description, and relationships"}],
"model": "gpt-4o-mini", "tool_choice": {"type": "function", "function": {"name":
"TaskEvaluation"}}, "tools": [{"type": "function", "function": {"name": "TaskEvaluation",
"description": "Correctly extracted `TaskEvaluation` with all the required parameters
with correct types", "parameters": {"$defs": {"Entity": {"properties": {"name":
{"description": "The name of the entity.", "title": "Name", "type": "string"},
"type": {"description": "The type of the entity.", "title": "Type", "type":
"string"}, "description": {"description": "Description of the entity.", "title":
"Description", "type": "string"}, "relationships": {"description": "Relationships
of the entity.", "items": {"type": "string"}, "title": "Relationships", "type":
"array"}}, "required": ["name", "type", "description", "relationships"], "title":
"Entity", "type": "object"}}, "properties": {"suggestions": {"description":
"Suggestions to improve future similar tasks.", "items": {"type": "string"},
"title": "Suggestions", "type": "array"}, "quality": {"description": "A score
from 0 to 10 evaluating on completion, quality, and overall performance, all
taking into account the task description, expected output, and the result of
the task.", "title": "Quality", "type": "number"}, "entities": {"description":
"Entities extracted from the task output.", "items": {"$ref": "#/$defs/Entity"},
"title": "Entities", "type": "array"}}, "required": ["entities", "quality",
"suggestions"], "type": "object"}}}]}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate
connection:
- keep-alive
content-length:
- '1962'
content-type:
- application/json
cookie:
- __cf_bm=nedOdWE1YnKQYt1kSbrcA.zhwa3bZDzmZqTOjZYER0c-1738700521-1.0.1.1-xQk9iXOvqvyXNhkIOgc8Ws2WYcT1mJFkDCvCC8xA5joFD8QfNrBIAr_Qs6sIxt2EzXyeFwBA6gA8ZgWApCHx0Q;
_cfuvid=Cl48aI8.jSRja0Pqr6Jrh3mAnigd4rDn6lhGicyjMPY-1738698987673-0.0.1.1-604800000
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.61.0
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.61.0
x-stainless-raw-response:
- 'true'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.8
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
content: "{\n \"id\": \"chatcmpl-AxJijOhk12Ua6lS23IwtZTachfjq9\",\n \"object\":
\"chat.completion\",\n \"created\": 1738700521,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_DSteeMHHPf5RanJb8qjCo4qx\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"TaskEvaluation\",\n
\ \"arguments\": \"{\\\"suggestions\\\":[\\\"Consider adding context
for the greeting to make it more engaging.\\\",\\\"Specify if any additional
information or tone is desired in the greeting.\\\"],\\\"quality\\\":10,\\\"entities\\\":[{\\\"name\\\":\\\"greeting\\\",\\\"type\\\":\\\"text\\\",\\\"description\\\":\\\"A
simple greeting phrase\\\",\\\"relationships\\\":[\\\"is a\\\",\\\"is part of
a conversation\\\"]}]}\"\n }\n }\n ],\n \"refusal\":
null\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 273,\n \"completion_tokens\":
67,\n \"total_tokens\": 340,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_bd83329f63\"\n}\n"
headers:
CF-RAY:
- 90cd5ed20cb267ee-SJC
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 04 Feb 2025 20:22:02 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- crewai-iuxna1
openai-processing-ms:
- '1624'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '30000'
x-ratelimit-limit-tokens:
- '150000000'
x-ratelimit-remaining-requests:
- '29999'
x-ratelimit-remaining-tokens:
- '149999876'
x-ratelimit-reset-requests:
- 2ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_4ee944acdd3928afbf6c5562403b064a
http_version: HTTP/1.1
status_code: 200
version: 1

View File

@@ -0,0 +1,184 @@
import pytest
from datetime import datetime
from crewai.utilities.events.events import on, emit
from crewai.utilities.events.agent_events import (
AgentExecutionStarted,
AgentExecutionCompleted,
AgentExecutionError,
)
from crewai.utilities.events.task_events import TaskStarted, TaskCompleted
from crewai.utilities.events.crew_events import CrewKickoffStarted, CrewKickoffCompleted
from crewai.crew import Crew
from crewai.agent import Agent
from crewai.task import Task
from unittest.mock import patch
from unittest import mock
base_agent = Agent(
role="base_agent",
llm="gpt-4o-mini",
goal="Just say hi",
backstory="You are a helpful assistant that just says hi",
)
base_task = Task(
description="Just say hi",
expected_output="hi",
agent=base_agent,
)
@pytest.mark.vcr(filter_headers=["authorization"])
def test_crew_emits_start_kickoff_event():
# Setup event listener
received_events = []
@on(CrewKickoffStarted)
def handle_crew_start(source, event):
received_events.append(event)
# Create a simple crew
crew = Crew(agents=[base_agent], tasks=[base_task], name="TestCrew")
# Run the crew
crew.kickoff()
# Verify the event was emitted
assert len(received_events) == 1
assert received_events[0].crew_name == "TestCrew"
assert isinstance(received_events[0].timestamp, datetime)
assert received_events[0].type == "crew_kickoff_started"
@pytest.mark.vcr(filter_headers=["authorization"])
def test_crew_emits_end_kickoff_event():
# Setup event listener
received_events = []
@on(CrewKickoffCompleted)
def handle_crew_end(source, event):
received_events.append(event)
# Create a simple crew
crew = Crew(agents=[base_agent], tasks=[base_task], name="TestCrew")
# Run the crew
crew.kickoff()
# Verify the event was emitted
assert len(received_events) == 1
assert received_events[0].crew_name == "TestCrew"
assert isinstance(received_events[0].timestamp, datetime)
assert received_events[0].type == "crew_kickoff_completed"
@pytest.mark.vcr(filter_headers=["authorization"])
def test_crew_emits_start_task_event():
# Setup event listener
received_events = []
@on(TaskStarted)
def handle_task_start(source, event):
received_events.append(event)
# Create a simple crew
crew = Crew(agents=[base_agent], tasks=[base_task], name="TestCrew")
# Run the crew
crew.kickoff()
# Verify the event was emitted
assert len(received_events) == 1
assert isinstance(received_events[0].timestamp, datetime)
assert received_events[0].type == "task_started"
@pytest.mark.vcr(filter_headers=["authorization"])
def test_crew_emits_end_task_event():
# Setup event listener
received_events = []
@on(TaskCompleted)
def handle_task_end(source, event):
received_events.append(event)
# Create a simple crew
crew = Crew(agents=[base_agent], tasks=[base_task], name="TestCrew")
# Run the crew
crew.kickoff()
# Verify the event was emitted
assert len(received_events) == 1
assert isinstance(received_events[0].timestamp, datetime)
assert received_events[0].type == "task_completed"
@pytest.mark.vcr(filter_headers=["authorization"])
def test_agent_emits_execution_error_event():
# Setup event listener
received_events = []
@on(AgentExecutionError)
def handle_agent_error(source, event):
received_events.append(event)
# Create an agent that will fail
failing_agent = Agent(
role="failing_agent",
goal="Fail execution",
backstory="You are an agent that will fail",
max_retry_limit=1, # Set low retry limit for testing
)
# Create a task that will trigger an error
failing_task = Task(
description="This will fail", agent=failing_agent, expected_output="hi"
)
error_message = "Forced error for testing"
# Mock the agent executor to raise an exception
with patch.object(failing_agent.agent_executor, "invoke") as mock_invoke:
mock_invoke.side_effect = Exception(error_message)
assert failing_agent._times_executed == 0
assert failing_agent.max_retry_limit == 1
# Execute task which should fail and emit error
with pytest.raises(Exception) as e:
failing_agent.execute_task(failing_task)
print("error message: ", e.value.args[0])
# assert e.value.args[0] == error_message
# assert failing_agent._times_executed == 2 # Initial attempt + 1 retry
# Verify the invoke was called twice (initial + retry)
mock_invoke.assert_has_calls(
[
mock.call(
{
"input": "This will fail\n\nThis is the expect criteria for your final answer: hi\nyou MUST return the actual complete content as the final answer, not a summary.",
"tool_names": "",
"tools": "",
"ask_for_human_input": False,
}
),
mock.call(
{
"input": "This will fail\n\nThis is the expect criteria for your final answer: hi\nyou MUST return the actual complete content as the final answer, not a summary.",
"tool_names": "",
"tools": "",
"ask_for_human_input": False,
}
),
]
)
print("made it here")
# Verify the error event was emitted
assert len(received_events) == 1
assert isinstance(received_events[0].timestamp, datetime)
assert received_events[0].type == "agent_execution_error"
assert received_events[0].agent == failing_agent
assert received_events[0].task == failing_task
assert error_message in received_events[0].error