Skip to content

Commit 467ee29

Browse files
authored
Improve EventListener and TraceCollectionListener for improved event… (#4160)
* Refactor EventListener and TraceCollectionListener for improved event handling - Removed unused threading and method branches from EventListener to simplify the code. - Updated event handling methods in EventListener to use new formatter methods for better clarity and consistency. - Refactored TraceCollectionListener to eliminate unnecessary parameters in formatter calls, enhancing readability. - Simplified ConsoleFormatter by removing outdated tree management methods and focusing on panel-based output for status updates. - Enhanced ToolUsage to track run attempts for better tool usage metrics. * clearer for knowledge retrieval and dropped some reduancies * Refactor EventListener and ConsoleFormatter for improved clarity and consistency - Removed the MCPToolExecutionCompletedEvent handler from EventListener to streamline event processing. - Updated ConsoleFormatter to enhance output formatting by adding line breaks for better readability in status content. - Renamed status messages for MCP Tool execution to provide clearer context during tool operations. * fix run attempt incrementation * task name consistency * memory events consistency * ensure hitl works * linting
1 parent b9dd166 commit 467ee29

File tree

8 files changed

+649
-1985
lines changed

8 files changed

+649
-1985
lines changed

lib/crewai/src/crewai/agents/agent_builder/base_agent_executor_mixin.py

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import time
44
from typing import TYPE_CHECKING
55

6+
from crewai.agents.parser import AgentFinish
67
from crewai.events.event_listener import event_listener
78
from crewai.memory.entity.entity_memory_item import EntityMemoryItem
89
from crewai.memory.long_term.long_term_memory_item import LongTermMemoryItem
@@ -29,7 +30,7 @@ class CrewAgentExecutorMixin:
2930
_i18n: I18N
3031
_printer: Printer = Printer()
3132

32-
def _create_short_term_memory(self, output) -> None:
33+
def _create_short_term_memory(self, output: AgentFinish) -> None:
3334
"""Create and save a short-term memory item if conditions are met."""
3435
if (
3536
self.crew
@@ -53,7 +54,7 @@ def _create_short_term_memory(self, output) -> None:
5354
"error", f"Failed to add to short term memory: {e}"
5455
)
5556

56-
def _create_external_memory(self, output) -> None:
57+
def _create_external_memory(self, output: AgentFinish) -> None:
5758
"""Create and save a external-term memory item if conditions are met."""
5859
if (
5960
self.crew
@@ -75,7 +76,7 @@ def _create_external_memory(self, output) -> None:
7576
"error", f"Failed to add to external memory: {e}"
7677
)
7778

78-
def _create_long_term_memory(self, output) -> None:
79+
def _create_long_term_memory(self, output: AgentFinish) -> None:
7980
"""Create and save long-term and entity memory items based on evaluation."""
8081
if (
8182
self.crew
@@ -136,40 +137,50 @@ def _create_long_term_memory(self, output) -> None:
136137
)
137138

138139
def _ask_human_input(self, final_answer: str) -> str:
139-
"""Prompt human input with mode-appropriate messaging."""
140-
event_listener.formatter.pause_live_updates()
141-
try:
142-
self._printer.print(
143-
content=f"\033[1m\033[95m ## Final Result:\033[00m \033[92m{final_answer}\033[00m"
144-
)
140+
"""Prompt human input with mode-appropriate messaging.
141+
142+
Note: The final answer is already displayed via the AgentLogsExecutionEvent
143+
panel, so we only show the feedback prompt here.
144+
"""
145+
from rich.panel import Panel
146+
from rich.text import Text
147+
148+
formatter = event_listener.formatter
149+
formatter.pause_live_updates()
145150

151+
try:
146152
# Training mode prompt (single iteration)
147153
if self.crew and getattr(self.crew, "_train", False):
148-
prompt = (
149-
"\n\n=====\n"
150-
"## TRAINING MODE: Provide feedback to improve the agent's performance.\n"
154+
prompt_text = (
155+
"TRAINING MODE: Provide feedback to improve the agent's performance.\n\n"
151156
"This will be used to train better versions of the agent.\n"
152-
"Please provide detailed feedback about the result quality and reasoning process.\n"
153-
"=====\n"
157+
"Please provide detailed feedback about the result quality and reasoning process."
154158
)
159+
title = "🎓 Training Feedback Required"
155160
# Regular human-in-the-loop prompt (multiple iterations)
156161
else:
157-
prompt = (
158-
"\n\n=====\n"
159-
"## HUMAN FEEDBACK: Provide feedback on the Final Result and Agent's actions.\n"
160-
"Please follow these guidelines:\n"
161-
" - If you are happy with the result, simply hit Enter without typing anything.\n"
162-
" - Otherwise, provide specific improvement requests.\n"
163-
" - You can provide multiple rounds of feedback until satisfied.\n"
164-
"=====\n"
162+
prompt_text = (
163+
"Provide feedback on the Final Result above.\n\n"
164+
"• If you are happy with the result, simply hit Enter without typing anything.\n"
165+
"• Otherwise, provide specific improvement requests.\n"
166+
"• You can provide multiple rounds of feedback until satisfied."
165167
)
168+
title = "💬 Human Feedback Required"
169+
170+
content = Text()
171+
content.append(prompt_text, style="yellow")
172+
173+
prompt_panel = Panel(
174+
content,
175+
title=title,
176+
border_style="yellow",
177+
padding=(1, 2),
178+
)
179+
formatter.console.print(prompt_panel)
166180

167-
self._printer.print(content=prompt, color="bold_yellow")
168181
response = input()
169182
if response.strip() != "":
170-
self._printer.print(
171-
content="\nProcessing your feedback...", color="cyan"
172-
)
183+
formatter.console.print("\n[cyan]Processing your feedback...[/cyan]")
173184
return response
174185
finally:
175-
event_listener.formatter.resume_live_updates()
186+
formatter.resume_live_updates()

lib/crewai/src/crewai/agents/crew_agent_executor.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from __future__ import annotations
88

99
from collections.abc import Callable
10+
import logging
1011
from typing import TYPE_CHECKING, Any, Literal, cast
1112

1213
from pydantic import BaseModel, GetCoreSchemaHandler
@@ -51,6 +52,8 @@
5152
from crewai.utilities.training_handler import CrewTrainingHandler
5253

5354

55+
logger = logging.getLogger(__name__)
56+
5457
if TYPE_CHECKING:
5558
from crewai.agent import Agent
5659
from crewai.agents.tools_handler import ToolsHandler
@@ -541,7 +544,7 @@ def _show_logs(self, formatted_answer: AgentAction | AgentFinish) -> None:
541544
if self.agent is None:
542545
raise ValueError("Agent cannot be None")
543546

544-
crewai_event_bus.emit(
547+
future = crewai_event_bus.emit(
545548
self.agent,
546549
AgentLogsExecutionEvent(
547550
agent_role=self.agent.role,
@@ -551,6 +554,12 @@ def _show_logs(self, formatted_answer: AgentAction | AgentFinish) -> None:
551554
),
552555
)
553556

557+
if future is not None:
558+
try:
559+
future.result(timeout=5.0)
560+
except Exception as e:
561+
logger.error(f"Failed to show logs for agent execution event: {e}")
562+
554563
def _handle_crew_training_output(
555564
self, result: AgentFinish, human_feedback: str | None = None
556565
) -> None:

0 commit comments

Comments
 (0)