mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-22 15:25:09 +00:00
fix: sync kickoff-completed event with OUTPUT hook result (#6571)
* fix: sync kickoff-completed event with OUTPUT hook result `CrewKickoffCompletedEvent` still carried the pre-hook `TaskOutput`, so AMP/OTEL consumers never saw `OUTPUT` mutations even though the returned `CrewOutput` was updated. Sync `final_task_output.raw` from the post-hook payload before emit, matching `FlowFinishedEvent`. * style: drop OUTPUT sync comment and rename crew output test
This commit is contained in:
@@ -1928,6 +1928,9 @@ class Crew(FlowTrackable, BaseModel):
|
||||
dispatch(InterceptionPoint.EXECUTION_END, end_ctx)
|
||||
crew_output = cast(CrewOutput, end_ctx.payload)
|
||||
|
||||
if isinstance(crew_output, CrewOutput):
|
||||
final_task_output.raw = crew_output.raw
|
||||
|
||||
# Ensure background memory saves finish (and emit their
|
||||
# completed/failed events) before the kickoff-completed event below
|
||||
# triggers listener teardown/finalization.
|
||||
|
||||
@@ -10,6 +10,9 @@ from __future__ import annotations
|
||||
from unittest.mock import patch
|
||||
|
||||
from crewai.agent import Agent
|
||||
from crewai.crew import Crew
|
||||
from crewai.events.event_bus import crewai_event_bus
|
||||
from crewai.events.types.crew_events import CrewKickoffCompletedEvent
|
||||
from crewai.flow.flow import Flow, listen, start
|
||||
from crewai.hooks.dispatch import (
|
||||
HookAborted,
|
||||
@@ -147,3 +150,34 @@ class TestTaskStepPoints:
|
||||
|
||||
assert result.raw == "sanitized output"
|
||||
assert (tmp_path / "output.txt").read_text() == "sanitized output"
|
||||
|
||||
|
||||
class TestCrewOutput:
|
||||
def test_output_modification_reaches_kickoff_completed_event(self):
|
||||
@on(InterceptionPoint.OUTPUT)
|
||||
def append_notice(ctx):
|
||||
if hasattr(ctx.payload, "raw") and isinstance(ctx.payload.raw, str):
|
||||
ctx.payload.raw += "\nchanged by hook"
|
||||
return None
|
||||
|
||||
completed_raw: list[str] = []
|
||||
|
||||
@crewai_event_bus.on(CrewKickoffCompletedEvent)
|
||||
def capture_completed(_source, event: CrewKickoffCompletedEvent):
|
||||
completed_raw.append(event.output.raw)
|
||||
|
||||
agent = Agent(role="Writer", goal="Write", backstory="Writes things.")
|
||||
task = Task(
|
||||
description="Write something",
|
||||
expected_output="Some text",
|
||||
agent=agent,
|
||||
)
|
||||
crew = Crew(agents=[agent], tasks=[task], verbose=False)
|
||||
|
||||
with patch.object(Agent, "execute_task", return_value="original output"):
|
||||
result = crew.kickoff()
|
||||
crewai_event_bus.flush()
|
||||
|
||||
assert result.raw.endswith("changed by hook")
|
||||
assert completed_raw
|
||||
assert completed_raw[-1].endswith("changed by hook")
|
||||
|
||||
Reference in New Issue
Block a user