fix(events): serialize deferred Pydantic state models - #6849
Open
andrewrfitz wants to merge 1 commit into
Open
Conversation
Deferred Pydantic serializers can remain unbuilt after nested validation, causing EventActions serialization to abort parallel tool response merges. Build nested model serializers before retrying serialization. Fixes google#6848
andrewrfitz
marked this pull request as ready for review
August 21, 2026 20:07
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Link to Issue or Description of Change
1. Link to an existing issue:
GoogleSearchAgentToolparallel responses fail to serialize deferredGroundingMetadata(MockValSer) #6848Problem:
A Pydantic model configured with
defer_build=Truecan retain a deferredMockValSerafter nested validation. When such a model is stored underEventActions.state_delta, duck-typed serialization fails before the existingunknown-value fallback can run. This aborts parallel function-response merging
when propagated grounding metadata is present.
Solution:
When normal state serialization fails, recursively build serializers for
Pydantic models in the state container and retry the original handler. Retrying
the handler preserves the caller's aliases and include/exclude directives. If
serialization still fails, the existing JSON-sanitizing fallback remains
unchanged for genuinely unsupported values such as callables.
Testing Plan
Unit Tests:
Passing checks:
pytest tests/unittests/events/test_event_actions.py tests/unittests/flows/llm_flows/test_functions_simple.py -q95 passedpytest tests/unittests/events/test_event_actions.py -qunder Python 3.10,3.11, 3.12, 3.13, and 3.14
17 passedon each versionmypy src/google/adk/events/event_actions.pySuccess: no issues found in 1 source filepre-commit run --files src/google/adk/events/event_actions.py tests/unittests/events/test_event_actions.pyuv buildFull-suite evidence:
pytest tests/unittests -n auto -q:12692 passed; the only two failureswere both cases of
test_entry_point_loads_only_allowlisted_packages, because the currentlocked environment eagerly loads
httpx2.origin/mainworktree.
tox -p autoran the full suite under Python 3.10 through 3.13. Each versionhad only those same two baseline failures, with 12,627–12,636 tests passing.
scipy==1.15.3has no compatible wheel and requires a Fortran compiler. The affected test
file passes in an isolated Python 3.14.6 environment using the project's
default dependencies.
Manual End-to-End (E2E) Tests:
GoogleSearchAgentToolparallel responses fail to serialize deferredGroundingMetadata(MockValSer) #6848 withgoogle-genai==2.19.0.Before the merge, the nested grounding model had a
MockValSer. After thischange, the merge completes, its serializer is a
SchemaSerializer, and themerged state preserves both values:
Checklist
CONTRIBUTING.mddocument.baseline failures are documented above).
Additional context
The regression test defines a fresh deferred Pydantic model and obtains the
nested value through parent-model validation. This avoids an order-dependent
test that could pass accidentally after another test has already built
GroundingMetadata's class serializer.