Skip to content

Conversation

@dpolistwm
Copy link

Problem Statement

Issue #1199 - Gemini thinking models (like gemini-3-pro-preview and gemini-3-flash-preview) require thought_signature to be preserved for function calls in multi-turn conversations. Without this, the API returns:

400 Bad Request: Unable to submit request because function call <tool_name> 
in the N. content block is missing a thought_signature.

Additionally, when no tools are provided, the implementation was sending empty tool arrays causing:

400 Bad Request: tools[0].tool_type: required one_of 'tool_type' 
must have one initialized field

Solution

This PR implements proper thought signature preservation for Gemini thinking models:

  1. Thought Signature Preservation: Captures thought_signature from function calls during streaming and includes it when sending function calls back to the API
  2. Base64 Encoding: Uses base64 encoding/decoding for binary thought_signature data (instead of UTF-8 which fails on binary data)
  3. Empty Tools Fix: Only includes tools parameter in the API request when there are actual tools to send
  4. Backwards Compatibility: Converts toolUse without thoughtSignature to text representation to handle old session history gracefully

Changes Made

src/strands/models/gemini.py:

  • Added base64 import for proper binary data encoding
  • Modified _format_request_content_part() to:
    • Decode base64 thoughtSignature when sending reasoningContent
    • Decode base64 thoughtSignature when sending toolUse with signature
    • Convert toolUse without thoughtSignature to text representation
  • Modified _format_request_tools() to only create Tool objects when tool_specs are provided
  • Modified _format_request_config() to conditionally include tools only when non-empty
  • Modified _format_chunk() to base64-encode thought_signature when capturing from streaming responses

tests/strands/models/test_gemini.py:

  • Updated test_stream_request_with_reasoning to use valid base64 signature
  • Updated test_stream_request_with_tool_use to include thoughtSignature
  • Added test_stream_request_with_tool_use_no_thought_signature for backwards compatibility
  • Updated test_stream_request_with_gemini_tools to expect correct tools format
  • Updated test_stream_response_reasoning to expect base64-encoded signature

Testing

  • ✅ All 33 existing Gemini model tests pass
  • ✅ Added new test for toolUse without thoughtSignature
  • ✅ Formatter and linter checks pass
  • ✅ Tested with actual Gemini thinking models in production

Alignment with Development Tenets

  • Simple at any scale: Handles both new thinking models and existing sessions transparently
  • Extensible by design: Preserves existing functionality while adding new capability
  • Composability: Works seamlessly with existing session management and conversation history
  • The obvious path is the happy path: Automatic fallback for old data prevents breaking changes

Breaking Changes

None - this is backwards compatible. Old sessions without thoughtSignature will have tool calls converted to text representation, preserving conversation context.

Closes #1199

- Preserve thought_signature for function calls in Gemini thinking models
- Fix empty tools list causing 400 Bad Request error
- Add base64 encoding/decoding for binary thought_signature data
- Add backwards compatibility for toolUse without thoughtSignature
- Update tests to reflect thought signature handling

Closes strands-agents#1199
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] INVALID_ARGUMENT using gemini-3-pro-preview

1 participant