Skip to content

Commit 211e2ce

Browse files
xuanyang15copybara-github
authored andcommitted
fix: skipping state_delta overwrite on function_response-only events
Co-authored-by: Xuan Yang <xygoogle@google.com> PiperOrigin-RevId: 911411431
1 parent 83f9817 commit 211e2ce

2 files changed

Lines changed: 36 additions & 7 deletions

File tree

src/google/adk/agents/llm_agent.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,17 @@ def __maybe_save_output_to_state(self, event: Event):
845845
# Handle text responses
846846
if event.is_final_response() and event.content and event.content.parts:
847847

848+
# Skip if no text parts at all to avoid overwriting state_delta values
849+
# already set (e.g. after_tool_callback with skip_summarization
850+
# on function_response-only events).
851+
has_text_part = any(
852+
part.text is not None and not part.thought
853+
for part in event.content.parts
854+
)
855+
856+
if not has_text_part:
857+
return
858+
848859
result = ''.join(
849860
part.text
850861
for part in event.content.parts
@@ -857,12 +868,6 @@ def __maybe_save_output_to_state(self, event: Event):
857868
if not result.strip():
858869
return
859870
result = validate_schema(self.output_schema, result)
860-
elif not result:
861-
# No text parts found and no output_schema. Skip to avoid
862-
# overwriting state_delta values already set by callbacks
863-
# (e.g. after_tool_callback with skip_summarization on
864-
# function_response-only events).
865-
return
866871
event.actions.state_delta[self.output_key] = result
867872

868873
@model_validator(mode='after')

tests/unittests/agents/test_llm_agent_output_save.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,9 @@ def test_maybe_save_output_to_state_handles_empty_final_chunk_with_schema(
279279

280280
def test_maybe_save_output_to_state_skips_function_response_only_event(self):
281281
"""Test that state_delta set by callback is not overwritten when event
282-
only has function_response parts and no text."""
282+
283+
only has function_response parts and no text.
284+
"""
283285
agent = LlmAgent(name="test_agent", output_key="result")
284286

285287
# Simulate a function_response-only event (no text parts)
@@ -307,3 +309,25 @@ def test_maybe_save_output_to_state_skips_function_response_only_event(self):
307309

308310
# The callback-set value should be preserved, not overwritten with ""
309311
assert event.actions.state_delta["result"] == [1, 2, 3]
312+
313+
def test_maybe_save_output_to_state_saves_empty_string_when_text_is_empty(
314+
self,
315+
):
316+
"""Test that output is saved as empty string when part.text is explicitly empty."""
317+
agent = LlmAgent(name="test_agent", output_key="result")
318+
319+
# Explicitly construct a part with empty string text
320+
parts = [types.Part(text="")]
321+
content = types.Content(role="model", parts=parts)
322+
event = Event(
323+
invocation_id="test_invocation",
324+
author="test_agent",
325+
content=content,
326+
actions=EventActions(),
327+
)
328+
329+
agent._LlmAgent__maybe_save_output_to_state(event)
330+
331+
# Assert key exists and value is empty string
332+
assert "result" in event.actions.state_delta
333+
assert not event.actions.state_delta["result"]

0 commit comments

Comments
 (0)