diff --git a/src/google/adk/agents/llm_agent.py b/src/google/adk/agents/llm_agent.py index 8b555b7497..a44fb6827e 100644 --- a/src/google/adk/agents/llm_agent.py +++ b/src/google/adk/agents/llm_agent.py @@ -841,6 +841,12 @@ def __maybe_save_output_to_state(self, event: Event): result = self.output_schema.model_validate_json(result).model_dump( exclude_none=True ) + elif not result: + # No text parts found and no output_schema. Skip to avoid + # overwriting state_delta values already set by callbacks + # (e.g. after_tool_callback with skip_summarization on + # function_response-only events). + return event.actions.state_delta[self.output_key] = result @model_validator(mode='after') diff --git a/tests/unittests/agents/test_llm_agent_output_save.py b/tests/unittests/agents/test_llm_agent_output_save.py index e904130105..ad7b48e3e2 100644 --- a/tests/unittests/agents/test_llm_agent_output_save.py +++ b/tests/unittests/agents/test_llm_agent_output_save.py @@ -276,3 +276,34 @@ def test_maybe_save_output_to_state_handles_empty_final_chunk_with_schema( # ASSERT: Because the method should return early, the state_delta # should remain empty. assert len(event.actions.state_delta) == 0 + + def test_maybe_save_output_to_state_skips_function_response_only_event(self): + """Test that state_delta set by callback is not overwritten when event + only has function_response parts and no text.""" + agent = LlmAgent(name="test_agent", output_key="result") + + # Simulate a function_response-only event (no text parts) + parts = [ + types.Part( + function_response=types.FunctionResponse( + name="my_tool", + response={"status": "success", "data": [1, 2, 3]}, + ) + ) + ] + content = types.Content(role="user", parts=parts) + + event = Event( + invocation_id="test_invocation", + author="test_agent", + content=content, + actions=EventActions( + skip_summarization=True, + state_delta={"result": [1, 2, 3]}, + ), + ) + + agent._LlmAgent__maybe_save_output_to_state(event) + + # The callback-set value should be preserved, not overwritten with "" + assert event.actions.state_delta["result"] == [1, 2, 3]