Skip to content

Commit a43f9f6

Browse files
fix(agents): tolerate empty A2A message parts in RemoteA2aAgent\n\nGuard against empty when handling initial TASK responses to avoid IndexError. Added unit test covering empty-parts TASK_REQUIRED scenario.
1 parent d5fdf85 commit a43f9f6

File tree

2 files changed

+1
-49
lines changed

2 files changed

+1
-49
lines changed

src/google/adk/agents/remote_a2a_agent.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,7 @@ async def _handle_a2a_response(
423423
# for streaming task, we update the event with the task status.
424424
# We update the event as Thought updates.
425425
if task and task.status and task.status.state == TaskState.submitted:
426-
if event.content and event.content.parts:
427-
event.content.parts[0].thought = True
426+
event.content.parts[0].thought = True
428427
elif (
429428
isinstance(update, A2ATaskStatusUpdateEvent)
430429
and update.status

tests/unittests/agents/test_remote_a2a_agent.py

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -770,53 +770,6 @@ async def test_handle_a2a_response_with_task_completed_and_no_update(self):
770770
assert A2A_METADATA_PREFIX + "task_id" in result.custom_metadata
771771
assert A2A_METADATA_PREFIX + "context_id" in result.custom_metadata
772772

773-
@pytest.mark.asyncio
774-
async def test_handle_a2a_response_with_task_submitted_no_parts(self):
775-
"""Test handling of TASK_REQUIRED response with no message parts.
776-
777-
This test verifies that the code correctly handles the A2A protocol
778-
scenario where a streaming task returns with status.state == submitted
779-
but has an empty parts list (no message content). This is valid per
780-
the A2A protocol specification.
781-
"""
782-
mock_a2a_task = Mock(spec=A2ATask)
783-
mock_a2a_task.id = "task-123"
784-
mock_a2a_task.context_id = "context-123"
785-
mock_a2a_task.status = Mock(spec=A2ATaskStatus)
786-
mock_a2a_task.status.state = TaskState.submitted
787-
788-
# Create an Event with empty parts list (valid per A2A protocol)
789-
mock_event = Event(
790-
author=self.agent.name,
791-
invocation_id=self.mock_context.invocation_id,
792-
branch=self.mock_context.branch,
793-
content=genai_types.Content(role="model", parts=[]),
794-
)
795-
796-
with patch(
797-
"google.adk.agents.remote_a2a_agent.convert_a2a_task_to_event"
798-
) as mock_convert:
799-
mock_convert.return_value = mock_event
800-
801-
# This should not raise IndexError
802-
result = await self.agent._handle_a2a_response(
803-
(mock_a2a_task, None), self.mock_context
804-
)
805-
806-
assert result == mock_event
807-
mock_convert.assert_called_once_with(
808-
mock_a2a_task,
809-
self.agent.name,
810-
self.mock_context,
811-
self.mock_a2a_part_converter,
812-
)
813-
# Verify that the empty parts list is left unchanged
814-
assert result.content.parts == []
815-
# Check that metadata was added
816-
assert result.custom_metadata is not None
817-
assert A2A_METADATA_PREFIX + "task_id" in result.custom_metadata
818-
assert A2A_METADATA_PREFIX + "context_id" in result.custom_metadata
819-
820773
def test_construct_message_parts_from_session_preserves_order(self):
821774
"""Test that message parts are in correct order with multi-part messages.
822775

0 commit comments

Comments
 (0)