diff --git a/lib/crewai/src/crewai/utilities/streaming.py b/lib/crewai/src/crewai/utilities/streaming.py index 8f43e8ef0..0cb1583ce 100644 --- a/lib/crewai/src/crewai/utilities/streaming.py +++ b/lib/crewai/src/crewai/utilities/streaming.py @@ -86,8 +86,8 @@ def _create_stream_chunk( content=event.chunk, chunk_type=chunk_type, task_index=current_task_info["index"], - task_name=current_task_info["name"], - task_id=current_task_info["id"], + task_name=event.task_name or current_task_info["name"], + task_id=event.task_id or current_task_info["id"], agent_role=event.agent_role or current_task_info["agent_role"], agent_id=event.agent_id or current_task_info["agent_id"], tool_call=tool_call_chunk, diff --git a/lib/crewai/tests/test_streaming.py b/lib/crewai/tests/test_streaming.py index 5860755ff..06741bf90 100644 --- a/lib/crewai/tests/test_streaming.py +++ b/lib/crewai/tests/test_streaming.py @@ -698,6 +698,64 @@ class TestStreamingEdgeCases: assert len(chunks) >= 1 assert streaming.is_completed + def test_streaming_chunks_contain_task_metadata_from_event( + self, researcher: Agent, simple_task: Task + ) -> None: + """Test that streaming chunks contain task_id and task_name from the event. + + This test verifies the fix for issue #4347 where streaming chunks were + missing task metadata (task_id/task_name were empty). + """ + crew = Crew( + agents=[researcher], + tasks=[simple_task], + verbose=False, + stream=True, + ) + + mock_output = MagicMock() + mock_output.raw = "Test output" + + original_kickoff = Crew.kickoff + call_count = [0] + test_task_id = "test-task-uuid-123" + test_task_name = "Test Task Name" + test_agent_id = "test-agent-uuid-456" + test_agent_role = "Test Agent Role" + + def mock_kickoff_fn(self: Any, inputs: Any = None, **kwargs: Any) -> Any: + call_count[0] += 1 + if call_count[0] == 1: + return original_kickoff(self, inputs, **kwargs) + else: + crewai_event_bus.emit( + crew, + LLMStreamChunkEvent( + type="llm_stream_chunk", + chunk="Hello from task", + task_id=test_task_id, + task_name=test_task_name, + agent_id=test_agent_id, + agent_role=test_agent_role, + ), + ) + return mock_output + + with patch.object(Crew, "kickoff", mock_kickoff_fn): + streaming = crew.kickoff() + assert isinstance(streaming, CrewStreamingOutput) + chunks = list(streaming) + + assert len(chunks) >= 1 + chunk_with_metadata = next( + (c for c in chunks if c.content == "Hello from task"), None + ) + assert chunk_with_metadata is not None + assert chunk_with_metadata.task_id == test_task_id + assert chunk_with_metadata.task_name == test_task_name + assert chunk_with_metadata.agent_id == test_agent_id + assert chunk_with_metadata.agent_role == test_agent_role + class TestStreamingImports: """Tests for correct imports of streaming types."""