You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
thinking_config is silently dropped with use_interactions_api=True #7924
Describe the Bug:
With Gemini(use_interactions_api=True), generate_content_config.thinking_config.thinking_level is never sent. build_generation_config doesn't map it to the interactions generation_config.thinking_level, and logs no warning.
Steps to Reproduce:
Create an LlmAgent with Gemini(use_interactions_api=True) and thinking_config=types.ThinkingConfig(thinking_level=types.ThinkingLevel.HIGH).
Run it with DEBUG logging on google_adk.google.adk.models.interactions_utils.
Check Generation Config in the "Interactions API Request" log.
Observed Behavior: Generation Config: {}. The model thinks at its default level.
Environment Details:
ADK Library Version (pip show google-adk): 2.13.0 (also main @ 8cd3b12)
Desktop OS: Linux
Python Version (python -V): 3.13
Model Information:
Are you using LiteLLM: No
Which model is being used: gemini-3.8-flash (Vertex AI)
🟡 Optional Information
Regression:
No. It has never been sent.
Logs:
Generation Config:
{}
Additional Context:
The interactions API accepts generation_config.thinking_level (minimal | low | medium | high); sending "high" directly gave about 2.5× the thought tokens. Similar: #7870 (output_schema), #7376 (temperature/top_p).
Thanks @jhackshaw, nice catch and the token numbers really help. Reproduced this on 2.13.0 and on current main: build_generation_config returns {} for thinking_level=HIGH even though the interactions GenerationConfigParam has the field.
Mapping the level to lowercase and skipping UNSPECIFIED, like #7926 does, gave {"thinking_level": "high"} and test_interactions_utils.py stayed green. One small thing: thinking_budget (and include_thoughts) still get dropped without any log, so a warning for the budget like the sampling params have might be worth adding.
Could you check that on your side and confirm it behaves well across the levels on a couple of models, including the 400 for an unsupported level? Once that’s tested #7926 should be good to go for review.
Thanks for reproducing it! I tested this live on Vertex AI (global, google-genai 2.34.0). Each request went through ADK's own Gemini model, once with use_interactions_api=True and once with generateContent as a baseline. The prompt was a counting puzzle and each cell is the median thought tokens of 3 runs.
With this PR
Model
Level
Interactions API
generateContent
gemini-3.8-flash
MINIMAL
400 Thinking level is unsupported: THINKING_LEVEL_MINIMAL
400 (same message)
LOW
524
613
MEDIUM
893
823
HIGH
1607
1697
gemini-3.1-pro-preview
MINIMAL
accepted, 2747 (runs: 6274, 2747, 2464)
400 thinking_level MINIMAL is not supported by this model
LOW
999
1060
MEDIUM
1520
1782
HIGH
2186
2119
gemini-3.1-flash-lite
MINIMAL
0
0
LOW
142
140
MEDIUM
866
1084
HIGH
7486
7659
On main (one run each), the level never arrives:
gemini-3.8-flash: MINIMAL succeeds (681) instead of returning a 400, and LOW/MEDIUM/HIGH come out at 876/778/796.
gemini-3.1-flash-lite: 0 thought tokens at every level, including HIGH. This model's default is minimal thinking, so the level is clearly dropped.
gemini-3.1-pro-preview: 5729/3637/2816/2557 for MINIMAL to HIGH. The counts don't follow the requested level.
Unsupported level. An unsupported level surfaces as a BadRequestError 400 from ADK, with the API's message matching what generateContent does for the same request.
thinking_budget / include_thoughts. I checked both against the Interactions schema in every supported google-genai release (2.30 through 2.34):
thinking_budget has no equivalent. It now logs a one-time warning, like the sampling params do. The warning points at thinking_level, or at turning off use_interactions_api. Tested with budgets of 0, -1, and 1024.
include_thoughts does have an equivalent: generation_config.thinking_summaries ("auto" / "none"). So the PR now maps True to "auto" and False to "none" instead of warning. Unset sends nothing, which keeps the API's default. I verified it live: the raw API returns summaries only with "auto", and the default sends none, which matches generateContent.
Thanks @jhackshaw, this is really thorough, and the per-model numbers make it clear the level never landed on main. Went through the updated diff (315e77b): the level mapping, the one-time thinking_budget warning and include_thoughts -> thinking_summaries all look right. The budget test is also safe across the 0/-1/1024 runs because the autouse fixture clears _WARNED_SAMPLING_PARAMS.
One gap: with thinking_summaries="auto" the summaries only reach ADK users in SSE mode. On the non-streaming path the ThoughtStep branch in interactions_utils.py (~L751) keeps only the signature and drops step.summary, so include_thoughts=True still shows no thought text there. Could you map the summary to a Part(text=..., thought=True) next to the signature part, the way _handle_thought_summary does for streaming, or call it out as a follow-up?
Also the PR description still only talks about thinking_level, so it’d be good to add the thinking_summaries mapping and the budget warning. This isn’t in any release yet (still reproduces on 2.13.0 and current main), so I’ll flag #7926 for maintainer review once that’s sorted.
Activity
surajksharma07 commentedon Nov 2, 2026
Thanks @jhackshaw, nice catch and the token numbers really help. Reproduced this on 2.13.0 and on current main: build_generation_config returns {} for thinking_level=HIGH even though the interactions GenerationConfigParam has the field.
Mapping the level to lowercase and skipping UNSPECIFIED, like #7926 does, gave {"thinking_level": "high"} and test_interactions_utils.py stayed green. One small thing: thinking_budget (and include_thoughts) still get dropped without any log, so a warning for the budget like the sampling params have might be worth adding.
Could you check that on your side and confirm it behaves well across the levels on a couple of models, including the 400 for an unsupported level? Once that’s tested #7926 should be good to go for review.
jhackshaw commentedon Nov 2, 2026
Thanks for reproducing it! I tested this live on Vertex AI (
global, google-genai 2.34.0). Each request went through ADK's ownGeminimodel, once withuse_interactions_api=Trueand once with generateContent as a baseline. The prompt was a counting puzzle and each cell is the median thought tokens of 3 runs.With this PR
Thinking level is unsupported: THINKING_LEVEL_MINIMALthinking_level MINIMAL is not supported by this modelOn
main(one run each), the level never arrives:Unsupported level. An unsupported level surfaces as a
BadRequestError400 from ADK, with the API's message matching what generateContent does for the same request.thinking_budget/include_thoughts. I checked both against the Interactions schema in every supported google-genai release (2.30 through 2.34):thinking_budgethas no equivalent. It now logs a one-time warning, like the sampling params do. The warning points atthinking_level, or at turning offuse_interactions_api. Tested with budgets of 0, -1, and 1024.include_thoughtsdoes have an equivalent:generation_config.thinking_summaries("auto"/"none"). So the PR now mapsTrueto"auto"andFalseto"none"instead of warning. Unset sends nothing, which keeps the API's default. I verified it live: the raw API returns summaries only with"auto", and the default sends none, which matches generateContent.surajksharma07 commentedon Nov 2, 2026
Thanks @jhackshaw, this is really thorough, and the per-model numbers make it clear the level never landed on main. Went through the updated diff (315e77b): the level mapping, the one-time thinking_budget warning and include_thoughts -> thinking_summaries all look right. The budget test is also safe across the 0/-1/1024 runs because the autouse fixture clears _WARNED_SAMPLING_PARAMS.
One gap: with thinking_summaries="auto" the summaries only reach ADK users in SSE mode. On the non-streaming path the ThoughtStep branch in interactions_utils.py (~L751) keeps only the signature and drops step.summary, so include_thoughts=True still shows no thought text there. Could you map the summary to a Part(text=..., thought=True) next to the signature part, the way _handle_thought_summary does for streaming, or call it out as a follow-up?
Also the PR description still only talks about thinking_level, so it’d be good to add the thinking_summaries mapping and the budget warning. This isn’t in any release yet (still reproduces on 2.13.0 and current main), so I’ll flag #7926 for maintainer review once that’s sorted.
jhackshaw commentedon Nov 2, 2026
Thanks @surajksharma07, nice catch. I updated to handle the non-streaming path and the PR description as well!
fix: send the thinking level on the interactions API