Skip to content

Add thought signature support for Google Gemini OpenAI compatibility#588

Merged
crmne merged 2 commits into
crmne:mainfrom
ericproulx:feature/openai-thought-signatures
Mar 1, 2026
Merged

Add thought signature support for Google Gemini OpenAI compatibility#588
crmne merged 2 commits into
crmne:mainfrom
ericproulx:feature/openai-thought-signatures

Conversation

@ericproulx

@ericproulx ericproulx commented Jan 29, 2026

Copy link
Copy Markdown
Contributor

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
@ericproulx ericproulx force-pushed the feature/openai-thought-signatures branch from caa78bf to 2991756 Compare February 17, 2026 13:17
@crmne crmne linked an issue Mar 1, 2026 that may be closed by this pull request
3 tasks
@crmne crmne merged commit a768457 into crmne:main Mar 1, 2026
19 checks passed
@codecov

codecov Bot commented Mar 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.89%. Comparing base (89709c7) to head (7d92719).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #588      +/-   ##
==========================================
+ Coverage   80.87%   80.89%   +0.01%     
==========================================
  Files         113      113              
  Lines        5129     5134       +5     
  Branches     1318     1320       +2     
==========================================
+ Hits         4148     4153       +5     
  Misses        981      981              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

[BUG] - Google Gemini OpenAI compatible endpoints thought signatures

2 participants