fix: route workflow IDs and retry jitter through platform seams#6468
Open
DABH wants to merge 2 commits into
Open
fix: route workflow IDs and retry jitter through platform seams#6468DABH wants to merge 2 commits into
DABH wants to merge 2 commits into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
DABH
force-pushed
the
platform-determinism-seams
branch
from
July 24, 2026 23:14
aa9bfb9 to
41aa6ac
Compare
ADK routes event IDs, invocation IDs, timestamps, and client function-call IDs through the injectable google.adk.platform providers so that embedders can customize how generated values are produced — for example to make agent runs deterministic and replayable. Three call sites on the workflow HITL/retry path still reach for the stdlib directly, which bypasses any installed provider: - RequestInput.interrupt_id defaults to uuid.uuid4(). Recorded user responses reference this ID, so an ID that regenerates differently on a replayed run breaks resume matching. - _ToolNode mints ToolContext.function_call_id with uuid.uuid4(). - Retry backoff jitter draws from the global random module (jitter defaults to 1.0 for any RetryConfig), making computed delays unreproducible. Add a google.adk.platform random seam (get_random / set_random_provider / reset_random_provider, exported via google.adk.platform per the visibility convention) mirroring the existing time and uuid providers, and route the three call sites through the platform seams. Default behavior is unchanged. The two existing jitter tests patched random.uniform globally; they now inject a mock through set_random_provider, exercising the new seam.
DABH
force-pushed
the
platform-determinism-seams
branch
from
July 24, 2026 23:16
41aa6ac to
95aeb2a
Compare
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.
Describe the bug
google.adk.platformprovides injectable time and uuid providers so that embedders can customize how generated values are produced - for example to make agent runs deterministic and reproducible for testing, simulation, or auditing. Event IDs, invocation IDs, timestamps, and client function-call IDs already route through them, but three call sites on the workflow HITL/retry path still call the stdlib directly, so they bypass any installed provider:events/request_input.py-RequestInput.interrupt_iddefaults touuid.uuid4(). This is the ID that recorded userFunctionResponses reference on resume; an ID minted outside the installed provider can't be reproduced, which breaks interrupt matching.workflow/_tool_node.py-ToolContext.function_call_idis minted withuuid.uuid4()instead ofplatform_uuid.new_uuid()(whichflows/llm_flows/functions.pyalready uses for the same purpose).workflow/utils/_retry_utils.py- retry backoff jitter draws from the globalrandommodule. Jitter defaults to 1.0 for anyRetryConfig, so every retried node computes an unreproducible delay.Describe the fix
google.adk.platform._randomwithget_random()/set_random_provider()/reset_random_provider(), exported fromgoogle.adk.platformper the visibility convention - mirroring the existingtime/uuidproviders (ContextVar-based, default = stdlibrandom.Random()).mock.patch('random.uniform', ...)to injecting a mock viaset_random_provider, exercising the new seam with the exact same assertions.This follows the injectable-provider approach also adopted in google/adk-java#1255.
Testing plan
New unit tests:
tests/unittests/platform/test_random.py- default provider, custom provider, reset (mirrorstest_uuid.py).tests/unittests/events/test_request_input.py- defaultinterrupt_idis a uuid; minted via the platform id provider; explicit id preserved.tests/unittests/workflow/test_tool_node.py::test_tool_node_function_call_id_uses_platform_id_provider- the tool receives a provider-mintedfunction_call_id.tests/unittests/workflow/utils/test_retry_utils.py::test_jitter_uses_platform_random_provider- a seeded provider makes the computed delay reproducible.All pre-commit hooks (isort, pyink, addlicense, new-file-prefix, ADK compliance, codespell) pass.