Skip to content

Gemini 3 function calls fail with missing thought_signature error after multiple tool uses #3705

Closed

Description

@haseryo0403

Describe the bug

When using Gemini 3 models with ADK's native Gemini integration (not LiteLLM), complex tasks involving multiple tool calls fail with a 400 error stating that function calls are missing thought_signature.

Important: This issue occurs even when using Gemini(model="gemini-3-pro-preview") directly, not LiteLLM. As mentioned in #3627 (comment) , the recommendation is to use ADK's native Gemini integration to avoid thought_signature issues, but this error shows that native integration alone does not solve the problem.

To Reproduce

from google.adk import Agent
from google.adk.models.google_llm import Gemini

agent = Agent(
    name="search_agent",
    model=Gemini(model="gemini-3-pro-preview"), # Using native Gemini, not LiteLLM
    tools=[google_search_tool],
)

# Execute complex task requiring multiple tool calls
response = await agent.ask_stream(
    messages=[Message(role=MessageRole.USER, contents=[
        TextContent(text="Complex task requiring multiple searches")
    ])]
)

Error

400 Bad Request
{
  "error": {
    "code": 400,
    "message": "Unable to submit request because function call `default_api:google_search` in the 5. content block is missing a `thought_signature`. Learn more: https://docs.cloud.google.com/vertex-ai/generative-ai/docs/thought-signatures",
    "status": "INVALID_ARGUMENT"
  }
}

The error occurs in the 5th content block after multiple tool invocations.

Expected behavior

ADK's native Gemini integration should automatically handle thought_signature requirements for function calling. Users should not need to manually manage this Gemini 3-specific requirement.

Environment

  • OS: macOS
  • Python version: 3.13
  • ADK version: Latest
  • Are you using LiteLLM: No (using native Gemini class)
  • Model: gemini-3-pro-preview

Additional context

Activity

  1. OhVIton commented on Nov 25, 2025

    @OhVIton

    👍

  2. Infinnerty commented on Nov 25, 2025

    @Infinnerty

    Same issue... why is working with ADK so painful at times.


    Environment:

    • google-adk: 1.19.0 (also tested dev branch commit e6be5bc)
    • google-genai: 1.52.0
    • Model: gemini-3-pro-preview
    • Endpoint: Vertex AI (global)

    Description:
    When using Gemini 3 with thinking enabled (ThinkingConfig(thinking_level="low", include_thoughts=True)),
    multi-turn function calling fails after 5+ sequential tool calls with:

    400 INVALID_ARGUMENT: function call default_api:get_fundamentals_data in the 8. content block
    is missing a thought_signature

    Reproduction:

    1. Create an LlmAgent with Gemini 3 and thinking enabled
    2. Give it tools that the model will call sequentially (e.g., fetching data for multiple tickers)
    3. Send a query that triggers 5+ sequential function calls
    4. Error occurs on the model call after the function responses

    Expected:
    ADK should preserve thought_signatures in conversation history when building subsequent LLM requests.

  3. added
    models[Component] This issue is related to model support
    on Nov 26, 2025
  4. surajksharma07 commented on Nov 26, 2025

    @surajksharma07
    Collaborator

    @haseryo0403 Thanks for reporting this.

    I've confirmed the issue - ADK isn't preserving thought_signatures when building conversation history for subsequent LLM calls (happens in src/google/adk/flows/llm_flows/contents.py:444).

    As a temporary workaround, you can remove the planner=BuiltInPlanner(thinking_config=...) from your agent to avoid the error, though you'll lose thinking capabilities.

    We'll look more into ADK's content processing to explicitly preserve thought_signature fields from model responses.

  5. surajksharma07 commented on Nov 26, 2025

    @surajksharma07
    Collaborator

    @wyf7107 Please have a look into it.

  6. added
    need attention[Status] This issue is important but the maintainers haven't started working on it
    on Nov 26, 2025
  7. haseryo0403 commented on Nov 26, 2025

    @haseryo0403
    Author

    @haseryo0403 Thanks for reporting this.

    I've confirmed the issue - ADK isn't preserving thought_signatures when building conversation history for subsequent LLM calls (happens in src/google/adk/flows/llm_flows/contents.py:444).

    As a temporary workaround, you can remove the planner=BuiltInPlanner(thinking_config=...) from your agent to avoid the error, though you'll lose thinking capabilities.

    We'll look more into ADK's content processing to explicitly preserve thought_signature fields from model responses.

    @surajksharma07 @wyf7107

    Thank you for identifying the root cause!

    I tried removing the planner=BuiltInPlanner(thinking_config=...) from my agent as you suggested, but unfortunately I'm still getting the same error.

    Is there anything else I should check or any other workaround I could try in the meantime?

    Thank you for your continued support!

  8. surajksharma07 commented on Nov 26, 2025

    @surajksharma07
    Collaborator

    @haseryo0403 Thanks for the update.

    Since you're still seeing the error even without the planner, it seems Gemini 3 might be generating thought_signatures automatically.

    Could you share your full agent setup code?
    I'd like to check if thinking is being enabled elsewhere (via generate_content_config or model defaults).

    Also, are you using the agent directly or through a Runner?
    This will help us narrow down where the thought_signatures are coming from and why ADK isn't preserving them in your specific case.

  9. haseryo0403 commented on Nov 26, 2025

    @haseryo0403
    Author

    @surajksharma07

    Current Configuration

    1. Agent Setup

    agent = Agent(
        name=app_name,
        description=self.DESCRIPTION,
        model=model,
        tools=tools,
        instruction=str(instruction) if instruction else RootAgentSystemPrompt.DEFAULT_INSTRUCTION,
    )
    
    return Runner(
        app_name=app_name,
        agent=agent,
        session_service=session_service,
        artifact_service=artifact_service,
    )

    NOT using planner=BuiltInPlanner(thinking_config=...)

    2. Runner Configuration

    events = runner.run_async(
        session_id=session.id,
        user_id=session.user_id,
        new_message=self.messages_to_adk_compatible_provider.to_single_content(
            new_user_messages, llm_model
        ),
        run_config=RunConfig(
            streaming_mode=StreamingMode.SSE,
            max_llm_calls=2500
        ),
    )

    No thinking configuration in RunConfig either.

    3. Models Used

    • gemini-3-pro-preview (GEMINI_30_PRO) ← Error occurs here
    • gemini-2.5-pro
    • gemini-2.5-flash

    4. Additional Context

    I do use ThinkingConfig(include_thoughts=False, thinking_budget=0) in two separate helper methods :

    # In __function_call_to_tool_use method 
    response = await client.models.generate_content(
        model='gemini-2.5-flash-lite',
        contents=prompt,
        config=GenerateContentConfig(
            thinking_config=ThinkingConfig(
                include_thoughts=False,
                thinking_budget=0
            ),
            response_mime_type='application/json',
            response_schema=ToolUseJsonSchema,
        ),
    )
    
    # In __function_response_to_tool_result method
    response = await client.models.generate_content(
        model='gemini-2.5-flash-lite',
        contents=prompt,
        config=GenerateContentConfig(
            thinking_config=ThinkingConfig(
                include_thoughts=False,
                thinking_budget=0
            ),
            response_mime_type='application/json',
            response_schema=ToolResultJsonSchema,
        ),
    )

    However, these are separate generate_content calls for generating summaries, not part of the main agent conversation flow managed by the Runner.


    Thank you for the continued investigation! I hope this information helps identify the cause.

  10. surajksharma07 commented on Nov 26, 2025

    @surajksharma07
    Collaborator

    @haseryo0403 Thank you for the detailed config.

    This clarifies things - you're not explicitly enabling thinking, but gemini-3-pro-preview appears to be generating thought_signatures by default (it's built into Gemini 3 models).

    The separate ThinkingConfig calls you mentioned aren't related since they use a different model.

    The core issue is that ADK's conversation history builder doesn't preserve thought_signatures regardless of whether thinking was explicitly requested or auto-enabled by the model.

    We're investigating a fix to ensure these signatures are maintained across all function calls.
    I'll keep you updated on progress.

  11. mark-lawrenson commented on Dec 3, 2025

    @mark-lawrenson

    We ran into this as well and implemented a workaround in before_model_callback.

    It seems ADK executes parallel tool calls sequentially, creating interleaved history:
    model(fc) -> user(fr) -> model(fc) -> user(fr)

    But Gemini expects them grouped:
    model([fc, fc]) -> user([fr, fr])

    We added logic in the callback to detect this interleaved pattern and merge the content blocks before sending to the LLM. This catches both in-memory turns and reloaded sessions.

    Also worth checking if thought_signature is being preserved correctly if you're using a custom session store - we had to make sure the binary blob survived serialization.

  12. surajksharma07 commented on Dec 6, 2025

    @surajksharma07
    Collaborator

    @mark-lawrenson Thanks for sharing that workaround.

    The interleaved history pattern issue you mentioned is a great insight.

    @haseryo0403 upgrading to v1.20.0 should help with thought_signature preservation (commits 31cfa3b, 632bf8b),
    but if you still see issues with parallel tool calls, mark-lawrenson's before_model_callback approach to merge interleaved content blocks is worth trying.

  13. 18 remaining items

  14. OhVIton commented on Dec 20, 2025

    @OhVIton

    👍

  15. ryanovas commented on Dec 21, 2025

    @ryanovas

    @surajksharma07 I have managed to get the side effects under control and will use progressive streaming for now, but it would be really nice to see this PR merged soon.

    My impression is that there's some excitement on the maintainers' side about this progressive streaming feature, and I see a commit now to enable it by default but I would urge you to reconsider that as in your own docs this is labelled as an experimental feature, and it fundamentally changes the behaviour in 2 key ways:

    • It introduces partial tool invocations that we have to change our code to account for and look like duplicate calls without explanation
    • It seems to make Gemini very eager to use tools and I had to change my prompts significantly to curb this

    I would make the case that we shouldn't have to use experimental features and make breaking changes to our code in order to support the newest version of the Google models in a framework called Google ADK. If people update their ADK version and suddenly have this enabled, it's going to be very confusing and disruptive.

    The ideal situation is to get the PR merged that fixes the base framework so we can use Gemini 3 out of the box 🙏

  16. surajksharma07 commented on Dec 22, 2025

    @surajksharma07
    Collaborator

    @ryanovas @VariableVic Important clarification on the fix status:

    v1.21.0 Status: PROGRESSIVE_SSE_STREAMING is still OFF by default in v1.21.0.
    The commit enabling it by default (0b1cff2) was made on Dec 19, 2025 - 8 days AFTER v1.21.0 was released (Dec 11).
    So v1.21.0 users must still manually set ADK_ENABLE_PROGRESSIVE_SSE_STREAMING=1.

    Current Status: The thought_signature issue is FIXED in the current development HEAD (after commit 0b1cff2). PROGRESSIVE_SSE_STREAMING is now enabled by default.

    Regarding PR #3858 - the fix was implemented directly via commits a5ac1d5, 786aaed, and 0b1cff2 rather than merging the PR.
    The interleaved history pattern issue is now resolved in HEAD.

    @ryanovas Your concerns about the experimental feature are valid.
    The excessive tool calling you're experiencing (issue #3974) is being investigated separately by @xuanyang15.
    The PROGRESSIVE_SSE_STREAMING feature is the current solution, but team is aware of the side effects.

    Recommendation: If the excessive tool use is manageable with prompt adjustments, continue with PROGRESSIVE_SSE_STREAMING=1 on v1.21.0.

    Team is looking more into the matter where both the thought_signature fix and the excessive tool use issue should be addressed.

    Thanks!

  17. ryanovas commented on Dec 28, 2025

    @ryanovas

    @surajksharma07 thanks for updating.

    Am I understanding correctly that the fix in question here is just enabling progressive streaming by default? The excessive tool use aside, as it's still possible that's just a me problem, you're proposing merging a breaking change to sidestep a bug - this isn't really fixing it as much as it is fixed when this feature is enabled.

    This means that anyone that upgrades from 1.21 to 1.22, even if they aren't using Gemini but are using SSE, will now start getting partial tool invocation calls and have to adjust their code to account for them. And anyone that wants to use the flagship Gemini models is forced to use this, and blocked until they make significant code changes. Not to mention it didn't fix the issue for the author of the PR with a proposed fix: #3858 (comment).

    I'm not sure I understand why there seems to be such an avoidance of fixing this without enabling progressive streaming. By your own docs this is still considered an experimental feature and when it runs on my machine I even get warnings in the logs about it.

    It is incredibly concerning to me that between this and other things like not including migrations for breaking changes with databases, or shipping things like event compaction completely broken using database session service, stability doesn't seem to be a major motivator for you guys. It feels like I can't ever expect to update ADK without having to come to the issues page on Github and figure out what changed and how to fix it.

  18. xuanyang15 commented on Dec 28, 2025

    @xuanyang15
    Collaborator

    @ryanovas Thanks for your feedback!

    1. The progressive sse streaming feature only affects Gemini models. If you are not using Gemini it will be a no-op enabling it.
    2. fix: merge interleaved function call/response contents to avoid thought_signature errors #3858 is not a correct fix As it will break model's understanding of the history. I have left a comment there, please take a look.
    3. As for it is experimental, it is actually following the feature rollout procedure: wip -> experimental, disabled by default -> experimental, enabled by default -> stable
    4. Could you please provide an example code to reproduce your issue? we will fix as soon as possible
  19. adk-bot commented on Jan 9, 2026

    @adk-bot
    Collaborator

    This issue has been automatically marked as stale because it has not had recent activity for 7 days after a maintainer requested clarification. It will be closed if no further activity occurs within 7 days.

  20. added
    stale[Status] Issues which have been marked inactive since there is no user response
    request clarification[Status] The maintainer need clarification or more information from the author
    on Jan 9, 2026
  21. adk-bot commented on Jan 17, 2026

    @adk-bot
    Collaborator

    This has been automatically closed because it has been marked as stale for over 7 days.

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

Metadata

Metadata

Labels

models[Component] This issue is related to model supportneeds review[Status] The PR/issue is awaiting review from the maintainerrequest clarification[Status] The maintainer need clarification or more information from the authorstale[Status] Issues which have been marked inactive since there is no user response

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions