From 1ee93c8bcb7ccd6f33658dc76b2095dd7e58aac9 Mon Sep 17 00:00:00 2001 From: Google Team Member Date: Tue, 28 Oct 2025 19:36:08 -0700 Subject: [PATCH] fix: do not consider events with state delta and no content as final response Previously this will return true for events yielded from before_agent_callback when there are state changes. Note with this change, it will also return false for state delta only callbacks even after main response, but this is fine as long as the actual final response event has it to be true. Closes #2992 PiperOrigin-RevId: 825313208 --- src/google/adk/events/event.py | 7 ----- tests/unittests/agents/test_base_agent.py | 35 ----------------------- 2 files changed, 42 deletions(-) diff --git a/src/google/adk/events/event.py b/src/google/adk/events/event.py index 3a4bba5f..8114d318 100644 --- a/src/google/adk/events/event.py +++ b/src/google/adk/events/event.py @@ -89,13 +89,6 @@ class Event(LlmResponse): """ if self.actions.skip_summarization or self.long_running_tool_ids: return True - - # If we see state delta but no content, then this must be an event fired - # from callbacks that does not early exit / override response, - # thus the event itself cannot be final response. - if self.actions.state_delta and self.content is None: - return False - return ( not self.get_function_calls() and not self.get_function_responses() diff --git a/tests/unittests/agents/test_base_agent.py b/tests/unittests/agents/test_base_agent.py index 2ecf8c90..663179f6 100644 --- a/tests/unittests/agents/test_base_agent.py +++ b/tests/unittests/agents/test_base_agent.py @@ -339,41 +339,6 @@ async def test_run_async_with_async_before_agent_callback_bypass_agent( assert events[0].content.parts[0].text == 'agent run is bypassed.' -@pytest.mark.asyncio -async def test_run_async_with_async_before_agent_callback_state_delta( - request: pytest.FixtureRequest, -): - def before_agent_callback_state_delta(callback_context: CallbackContext): - callback_context.state['some_field'] = 'some_value' - return None - - agent = _TestingAgent( - name=f'{request.function.__name__}_test_agent', - before_agent_callback=before_agent_callback_state_delta, - ) - parent_ctx = await _create_parent_invocation_context( - request.function.__name__, agent - ) - - events = [e async for e in agent.run_async(parent_ctx)] - - # The before_agent_callback yields an event with state change. - # Then the agent's _run_async_impl yields another event. - assert len(events) == 2 - - callback_event = events[0] - # The callback event should have state delta and no content. - assert callback_event.actions.state_delta is not None - assert callback_event.actions.state_delta['some_field'] == 'some_value' - assert callback_event.content is None - # This should not be a final response. - assert not callback_event.is_final_response() - - agent_run_event = events[1] - # The event from the agent run should be a final response. - assert agent_run_event.is_final_response() - - class CallbackType(Enum): SYNC = 1 ASYNC = 2