Skip to content

Add thought signature support for Google Gemini OpenAI compatibility#588

Open
ericproulx wants to merge 1 commit intocrmne:mainfrom
ericproulx:feature/openai-thought-signatures
Open

Add thought signature support for Google Gemini OpenAI compatibility#588
ericproulx wants to merge 1 commit intocrmne:mainfrom
ericproulx:feature/openai-thought-signatures

Conversation

@ericproulx
Copy link

@ericproulx ericproulx commented Jan 29, 2026

Summary

This PR adds support for preserving and transmitting thought signatures when using Google Gemini models through the OpenAI-compatible API. This enables seamless integration with Gemini's extended reasoning capabilities while maintaining compatibility with the OpenAI API format.

Background

Google Gemini models support extended reasoning through "thinking" modes, which generate thought signatures that need to be preserved when working with tool calls. When using Gemini models through an OpenAI-compatible endpoint, these thought signatures are transmitted in the extra_content.google.thought_signature field, following the OpenAI Realtime API's extension pattern.

Changes

Provider Implementation

  • lib/ruby_llm/providers/openai/tools.rb:
    • Added extract_tool_call_thought_signature method to extract signatures from incoming tool calls
    • Modified parse_tool_calls to preserve thought signatures in ToolCall objects
    • Updated format_tool_calls to include extra_content.google.thought_signature when present

Testing

  • spec/ruby_llm/providers/open_ai/tools_spec.rb (new file):
    • Comprehensive test coverage for parsing tool calls with and without thought signatures
    • Tests for formatting tool calls with thought signature preservation
    • Tests for the signature extraction helper method
    • Edge case handling (nil, empty, missing fields)

Technical Details

Incoming Tool Calls (Parsing)

When receiving tool calls from Gemini through the OpenAI-compatible API:

{
  'id' => 'call_456',
  'function' => { 'name' => 'weather', 'arguments' => '{"location":"Paris"}' },
  'extra_content' => {
    'google' => { 'thought_signature' => 'sig_abc123' }
  }
}

The signature is now extracted and stored in the ToolCall object.

Outgoing Tool Calls (Formatting)

When sending tool calls back to the API, thought signatures are preserved:

{
  id: 'call_456',
  type: 'function',
  function: { name: 'weather', arguments: '{"location":"Paris"}' },
  extra_content: {
    google: { thought_signature: 'sig_abc123' }
  }
}

Why This Matters

  1. Google Gemini Compatibility: Enables full support for Gemini's thinking modes when using OpenAI-compatible endpoints
  2. Reasoning Preservation: Maintains the connection between reasoning steps and tool calls
  3. API Standard Alignment: Follows the OpenAI Realtime API's extra_content extension pattern
  4. Backward Compatibility: Tool calls without thought signatures continue to work exactly as before

Backward Compatibility

Fully backward compatible:

  • Tool calls without thought signatures are handled identically to before
  • No changes to the public API
  • All existing tests continue to pass
  • Only adds optional signature handling

Testing

  • ✅ New comprehensive test suite for OpenAI tools module
  • ✅ Tests for both parsing and formatting with/without signatures
  • ✅ Edge cases handled (nil, empty inputs, missing fields)
  • ✅ Existing functionality preserved

Related Documentation

This change aligns with:

This change enables RubyLLM to preserve and transmit thought signatures when using Google Gemini models through the OpenAI-compatible API. Thought signatures are part of Gemini's extended reasoning capabilities and need to be preserved in the extra_content field when working with tool calls.

Changes:
- Extract thought signatures from extra_content.google.thought_signature in incoming tool calls
- Include thought signatures in outgoing tool calls when present
- Add comprehensive test coverage for thought signature handling
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