Repository navigation
fix(adk): carry donkey.last_call into after_model_callback on google-adk 2.13 - #1214
Merged
Merged
Conversation
…adk 2.13 (#1207) google-adk 2.13.0 iterates the model's response generator in a copy of the flow's context (_stream_in_caller_scope), so the record the transport set stayed in that copy and an after_model_callback read UNOBSERVED. donkey.adk.gemini() and donkey.adk.model() now return a lazily defined subclass of Gemini / LiteLlm (GovernedGemini / GovernedLiteLlm) whose generate_content_async, a plain def, opens a LastCallBridge in the flow's context before ADK copies it. The bridge closes before the first complete (non-partial) response, because ADK runs that response's function calls, in tasks of their own, before resuming the generator (hazard #2). isinstance against the ADK classes still holds, so verify_frameworks.py's expected-class check passes. Works on 2.4.0 (floor), 2.12.0 (lock) and 2.13.0; no version ceiling (§8.4). Tests: model() Runner + after_model_callback, a streamed Runner run, a task started on a complete response, and isinstance. The Runner tests fail on 2.13.0 without the fix; the task test fails without the close-before-complete step. Docs (§0.3): verified-apis.md §8 Google ADK rows record the 2.13.0 offline re-check, and fix the native Gemini row's "replaces wholesale" wording: 2.13's Gemini._with_adk_http_options merges ADK's tracking headers into the caller's http_options and fills only unset fields. adk.mdx updated to match; llms artifacts regenerated. Refs #1207 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 25, 2026
This was referenced Oct 25, 2026
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.
Refs #1207
This PR intentionally leaves the framework-release issue open:
framework-release-watch.ymlshuts it once the lock moves to google-adk 2.13.0. This PR does not changeconstraints/adapter-contract-adk-py3.12.txt; the lock refresh does that.Summary
google.adk.utils._runner_utils._stream_in_caller_scope). The record the transport sets stays in that copy, so anafter_model_callbackreadUNOBSERVED. That is whytest_adk_runner_is_unobserved_but_after_model_callback_sees_itfailed on 2.13.0.donkey.adk.gemini()anddonkey.adk.model()now return a lazily defined subclass ofGemini/LiteLlm(GovernedGemini/GovernedLiteLlm, built by_last_call_bridged_class). The class is defined on first use, sogoogle.adkis still imported lazily (§1.1). Strands'_governed_model_classis the precedent.BaseLlm.generate_content_async, as a plaindef. It opens aLastCallBridgein the flow's context before ADK copies that context, the same pattern as the langgraph bridge.isinstanceagainst the ADK classes still holds, soverify_frameworks.py's expected-class check passes. The actual class it prints isdonkey_kit.integrations.adk.GovernedGemini/GovernedLiteLlm.docs/verified-apis.md(Google ADK; Google ADK (native Gemini)).client_kwargsreplaces ... wholesale" wording is fixed. On 2.13,Gemini._with_adk_http_optionsfills only theapi_version/base_url/retry_optionsthe caller left unset, and merges ADK's tracking values into the caller'sheaders.MockTransportcapture shows the wire is unchanged between 2.12.0 and 2.13.0 apart from thegoogle-adk/<version>token.website/content/frameworks/adk.mdxis updated to match, and the llms artifacts are regenerated.Test plan
New tests in
tests/unit/test_adapter_async_last_call.py:test_adk_model_runner_is_unobserved_but_after_model_callback_sees_it: the Gemini Runner test, formodel().test_adk_streamed_run_after_model_callback_sees_every_response: an SSE Runner run, where every partial and the final callback readOBSERVED.test_adk_bridge_closes_before_a_complete_response: a task started on a complete response records in its own context.test_adk_factories_return_the_adk_classes: theisinstancecheck.Fail before the fix, pass after:
Gate, run from
python/:nox -s typecheck-and-lint test-3.11: both succeed (ruff,ruff format --check, mypy --strict, lint-imports, vulture; test-3.11 green).nox -s "adk-stacks(google-adk>=2.4)" "adk-stacks(google-adk==2.4.0)" "adapter-contract(adk)": all succeed.>=2.4leg resolved google-adk 2.13.0: 87 passed, 73 skipped.adapter-contract(adk)on the 2.12.0 lock: 3468 passed, 228 skipped, andsmoke_example.py adkpassed.pytest -qon the PR lock with only google-adk moved to 2.13.0: 3468 passed, 228 skipped.scripts/smoke_example.py adkpassed.python scripts/verify_frameworks.py --only adk --emit-verifiedon 2.13.0 and 2.4.0, plus--only adkon 2.12.0: signature ok and expected ok foradkandadk.gemini. Live was not run.nox -s docs-llms-drift docs-site: both succeed.scripts/check_commit_identities.py origin/develop..HEAD: rc 0. Thenew-dependenciessession needs a barepythonon PATH and couldn't run locally; this diff doesn't touchpyproject.toml.Not run:
--live(no live round-trip on 2.13.0).Pre-existing, not caused by this PR: offline, with the recorded
responses.stream.*fixture, a streamed ADK Gemini call leavesdonkey.last_call.input_tokensasNoneon 2.12.0 and 2.13.0, with or without the bridge. This is recorded in the §8 row. The adk page's "usage lands on the last one" for streaming is not confirmed by this offline check and may deserve a follow-up issue.ADR needed?
Post-deploy steps
None. When the lock refresh moves
adapter-contract-adk-py3.12.txtto google-adk 2.13.0,framework-release-watch.ymlshuts the framework-release issue.🤖 Generated with Claude Code