From ed2c3ebde9cafbb5e2bf375f44db1e77cee9fb24 Mon Sep 17 00:00:00 2001 From: Google Team Member Date: Thu, 15 Jan 2026 10:03:05 -0800 Subject: [PATCH] fix: Prevent stopping event processing on events with None content PiperOrigin-RevId: 856706510 --- src/google/adk/agents/remote_a2a_agent.py | 11 ++++++++++- .../unittests/agents/test_remote_a2a_agent.py | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/google/adk/agents/remote_a2a_agent.py b/src/google/adk/agents/remote_a2a_agent.py index 16732884..23a9b475 100644 --- a/src/google/adk/agents/remote_a2a_agent.py +++ b/src/google/adk/agents/remote_a2a_agent.py @@ -348,6 +348,13 @@ class RemoteA2aAgent(BaseAgent): return a2a_message + def _is_remote_response(self, event: Event) -> bool: + return ( + event.author == self.name + and event.custom_metadata + and event.custom_metadata.get(A2A_METADATA_PREFIX + "response", False) + ) + def _construct_message_parts_from_session( self, ctx: InvocationContext ) -> tuple[list[A2APart], Optional[str]]: @@ -365,7 +372,7 @@ class RemoteA2aAgent(BaseAgent): events_to_process = [] for event in reversed(ctx.session.events): - if event.author == self.name: + if self._is_remote_response(event): # stop on content generated by current a2a agent given it should already # be in remote session if event.custom_metadata: @@ -496,6 +503,8 @@ class RemoteA2aAgent(BaseAgent): invocation_id=ctx.invocation_id, branch=ctx.branch, ) + event.custom_metadata = event.custom_metadata or {} + event.custom_metadata[A2A_METADATA_PREFIX + "response"] = True return event except A2AClientError as e: logger.error("Failed to handle A2A response: %s", e) diff --git a/tests/unittests/agents/test_remote_a2a_agent.py b/tests/unittests/agents/test_remote_a2a_agent.py index d395a551..6a098dff 100644 --- a/tests/unittests/agents/test_remote_a2a_agent.py +++ b/tests/unittests/agents/test_remote_a2a_agent.py @@ -683,7 +683,16 @@ class TestRemoteA2aAgentMessageHandling: agent1 = Mock() agent1.content = content2 agent1.author = self.agent.name - agent1.custom_metadata = None + agent1.custom_metadata = { + A2A_METADATA_PREFIX + "response": True, + } + + agent2 = Mock() + agent2.content = None + agent2.author = self.agent.name + # Just actions, no content. Not marked as a response. + agent2.actions = Mock() + agent2.custom_metadata = None part3 = Mock() part3.text = "User 2" @@ -694,7 +703,7 @@ class TestRemoteA2aAgentMessageHandling: user2.author = "user" user2.custom_metadata = None - self.mock_session.events = [user1, agent1, user2] + self.mock_session.events = [user1, agent1, user2, agent2] def mock_converter(part): mock_a2a_part = Mock() @@ -785,7 +794,10 @@ class TestRemoteA2aAgentMessageHandling: agent1 = Mock() agent1.content = content2 agent1.author = self.agent.name - agent1.custom_metadata = {A2A_METADATA_PREFIX + "context_id": "ctx-1"} + agent1.custom_metadata = { + A2A_METADATA_PREFIX + "response": True, + A2A_METADATA_PREFIX + "context_id": "ctx-1", + } part3 = Mock() part3.text = "User 2"