Skip to content

Apply Google ADK deterministic providers inside workflow tasks - #1854

Open
DABH wants to merge 2 commits into
mainfrom
fix/adk-providers-in-workflow-threads
Open

Apply Google ADK deterministic providers inside workflow tasks#1854
DABH wants to merge 2 commits into
mainfrom
fix/adk-providers-in-workflow-threads

Conversation

@DABH

@DABH DABH commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

ADK keeps its time and uuid providers in contextvars.ContextVars, and GoogleAdkPlugin set them from the worker's context. Workflow tasks run on the workflow task executor's threads, which start with an empty context, so inside a workflow ADK still used wall-clock time and uuid.uuid4() for session, event, invocation, and function-call ids. Only debug mode, which runs activations inline, saw the deterministic values.

The plugin now rebinds each google.adk.platform ContextVar (time, uuid, and the random seam added in ADK 2.8.0) to one whose default is the Temporal provider, so it applies in every context on Worker and Replayer, sandboxed or not. Installation is idempotent; outside a workflow the providers fall back to the standard library.

Breaking: the google-adk extra now requires google-adk>=2.8.0, the first release with the _random seam.

Tested with a real Worker (sandboxed and unsandboxed) plus replay, and a fresh-thread check that fails on main. Lock and doc notes are in the first comment.

Same approach as _install_provider in #1675, which can rebase onto this.

ADK keeps its time, id, and random providers in contextvars.ContextVars.
GoogleAdkPlugin set them in the worker's context, but workflow tasks run
on the workflow task executor's threads, which start with an empty
context, so ADK code inside a workflow read the defaults: wall-clock time
and uuid.uuid4() for session, event, invocation, and function-call ids.
Only debug mode, which runs activations inline, saw the deterministic
values.

Rebind each google.adk.platform ContextVar to one whose default is the
Temporal provider so it is visible from every context, on Worker and
Replayer alike. Also install the random provider ADK added in 2.8.0 and
raise the google-adk floor to 2.8.0.
@DABH
DABH requested review from a team as code owners September 11, 2026 06:07
Use workflow.time() for the time provider, warn when installing replaces
a provider set earlier in the calling context, and document that
overrides must be made after the worker starts and that ADK id and
random generation raise ReadOnlyContextError in read-only contexts.
Tests assert provider identity.
@DABH

DABH commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Notes for review:

  • uv.lock: besides google-adk 2.4.0 -> 2.8.0, the diff carries google-genai 2.11.0 -> 2.20.0 (ADK 2.8.0 requires google-genai>=2.19), a new aiohttp edge, and marker/exclude-newer re-serialization from a newer uv. uv lock --check passes.
  • Behaviour documented in the CHANGELOG and README: installation warns if it replaces an ADK provider set earlier in the calling context (overrides must be made after the worker starts or from workflow code), and, like workflow.uuid4(), ADK id generation and get_random() in query handlers and update validators now raise ReadOnlyContextError instead of returning a random value.
  • The README's "Support for custom span exporters" bullet is removed as a stale-doc cleanup, unrelated to the fix.
  • Validation: uv run pytest tests/contrib/google_adk_agents -> 58 passed, 5 skipped (tests needing GOOGLE_API_KEY and the CI-skipped MCP tests); uv run poe lint (ruff, pyright, mypy, basedpyright, pydocstyle) passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant