from typing import Any from Agent_E.ae.utils.logger import logger def is_agent_stuck_in_loop(messages: list[dict[str, Any]]) -> bool: """ Detects loops in the agent's responses by iterating over the last N responses. Parameters ---------- messages : list[dict[str, Any]] A list of dictionaries representing the agent's messages. Returns ------- bool True if a loop is detected, False otherwise. """ number_of_turns_to_check_for_loops: int = 6 number_of_rounds_to_check_for_loops: int = number_of_turns_to_check_for_loops // 2 #integer division since we are checking for pairs of messages and can't have fractions # Detect any loops by checking the last number_of_rounds_to_check_for_loops tool responses and their corresponding tool calls if len(messages) > number_of_turns_to_check_for_loops: last_six_items = messages[-number_of_turns_to_check_for_loops:] logger.debug(f"More than {number_of_turns_to_check_for_loops} messages in the conversation. Checking for loops..") # Filter items by role tool_calls = [item for item in last_six_items if item.get("role") == "assistant"] # Check if function attributes are the same for tool items if tool_calls: tool_functions = [item.get("tool_calls", [{}])[0].get("function") for item in tool_calls] logger.debug(f"Last {number_of_rounds_to_check_for_loops} tool calls: {tool_functions}") if all(func == tool_functions[0] for func in tool_functions): logger.debug(f"Last {number_of_rounds_to_check_for_loops} tool calls are identical. Checking Tool responses..") # Check if content attributes are the same for assistant items tool_responses = [item for item in last_six_items if item.get("role") == "tool"] if tool_responses: assistant_contents = [item.get("content") for item in tool_responses] logger.debug(f"Last N tool responses: {assistant_contents}") if all(content == assistant_contents[0] for content in assistant_contents): logger.debug(f"Last {number_of_rounds_to_check_for_loops} tool responses are identical. Terminating") logger.info("Terminating browser executor since a loop was detected...") return True return False