Compare commits

...

1 Commits

Author SHA1 Message Date
Devin AI
41ec7f6ce0 fix: populate task_id and task_name in streaming chunks from event
Fixes #4347 - Crew streaming chunks were missing task metadata (task_id/task_name empty).

The issue was in _create_stream_chunk() which only used current_task_info for
task_name and task_id, ignoring the values from the LLMStreamChunkEvent. This
is inconsistent with how agent_role and agent_id were handled (preferring event
values).

The fix updates _create_stream_chunk() to use event.task_name and event.task_id
when available, falling back to current_task_info values otherwise.

Added test to verify streaming chunks contain task metadata from events.

Co-Authored-By: João <joao@crewai.com>
2026-02-03 12:45:48 +00:00
2 changed files with 60 additions and 2 deletions

View File

@@ -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,

View File

@@ -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."""