Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Bug Fixes

* fix(agents): tolerate empty A2A message parts in RemoteA2aAgent; add unit test ([fix/a2a-handle-empty-parts])

## [1.20.0](https://github.com/google/adk-python/compare/v1.19.0...v1.20.0) (2025-12-01)


Expand Down Expand Up @@ -40,7 +46,6 @@

* Add Code Wiki badge to README ([caf23ac](https://github.com/google/adk-python/commit/caf23ac49fe08bc7f625c61eed4635c26852c3ba))


## [1.19.0](https://github.com/google/adk-python/compare/v1.18.0...v1.19.0) (2025-11-19)

### Features
Expand Down
10 changes: 8 additions & 2 deletions src/google/adk/agents/remote_a2a_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,14 @@ async def _handle_a2a_response(
)
# for streaming task, we update the event with the task status.
# We update the event as Thought updates.
if task and task.status and task.status.state == TaskState.submitted:
event.content.parts[0].thought = True
if (
task
and task.status
and task.status.state == TaskState.submitted
and event.content.parts
):
for part in event.content.parts:
part.thought = True
elif (
isinstance(update, A2ATaskStatusUpdateEvent)
and update.status
Expand Down
39 changes: 39 additions & 0 deletions tests/unittests/agents/test_remote_a2a_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,45 @@ async def test_handle_a2a_response_with_partial_artifact_update(self):

assert result is None

@pytest.mark.asyncio
async def test_handle_a2a_response_with_task_submitted_and_empty_parts(self):
"""Test handling of a task submitted response with empty parts."""
mock_a2a_task = Mock(spec=A2ATask)
mock_a2a_task.id = "task-123"
mock_a2a_task.context_id = "context-123"
mock_a2a_task.status = Mock(spec=A2ATaskStatus)
mock_a2a_task.status.state = TaskState.submitted

# Create a proper Event mock that can handle custom_metadata
# Content with empty parts
mock_event = Event(
author=self.agent.name,
invocation_id=self.mock_context.invocation_id,
branch=self.mock_context.branch,
content=genai_types.Content(role="model", parts=[]),
)

with patch(
"google.adk.agents.remote_a2a_agent.convert_a2a_task_to_event"
) as mock_convert:
mock_convert.return_value = mock_event

result = await self.agent._handle_a2a_response(
(mock_a2a_task, None), self.mock_context
)

assert result == mock_event
mock_convert.assert_called_once_with(
mock_a2a_task,
self.agent.name,
self.mock_context,
self.mock_a2a_part_converter,
)
# Check that metadata was added
assert result.custom_metadata is not None
assert A2A_METADATA_PREFIX + "task_id" in result.custom_metadata
assert A2A_METADATA_PREFIX + "context_id" in result.custom_metadata


class TestRemoteA2aAgentMessageHandlingFromFactory:
"""Test message handling functionality."""
Expand Down
Loading