Skip to content

Conversation

finbarr
Copy link
Contributor

@finbarr finbarr commented Aug 21, 2025

Summary

  • Fixes API errors when using tools with array-type parameters in both Gemini and OpenAI providers
  • Adds required items field for array parameters in tool declarations
  • Resolves errors like: GenerateContentRequest.tools[0].function_declarations[2].parameters.properties[fields].items: missing field

Problem

Both Gemini and OpenAI APIs require an items field for array-type parameters in tool/function declarations to specify the type of array elements. Without this field, tools with array parameters fail with missing field errors or may not work correctly.

Solution

Modified the parameter formatting methods in both providers to automatically add the items field for all array-type parameters:

  • Gemini: Added items: { type: 'STRING' } in format_parameters method
  • OpenAI: Added items: { type: 'string' } in param_schema method

Changes

  • Modified lib/ruby_llm/providers/gemini/tools.rb to add items field for array types
  • Modified lib/ruby_llm/providers/openai/tools.rb to add items field for array types
  • Added comprehensive tests in spec/ruby_llm/providers/gemini/tools_spec.rb
  • Added comprehensive tests in spec/ruby_llm/providers/openai/tools_spec.rb

Test Plan

  • All existing tests pass
  • New unit tests for array parameter formatting in both providers
  • Integration tests verify proper tool formatting with mixed parameter types
  • Rubocop linting passes
  • Verified fix matches the working monkey patch from production usage (Gemini)
  • Tested with actual tool calls for both providers

This resolves issues when using tools with array parameters in both Gemini and OpenAI models, enabling proper function calling with arrays across multiple providers.

🤖 Generated with Claude Code

finbarr and others added 3 commits August 21, 2025 10:28
The Gemini API requires an 'items' field for array-type parameters
in tool declarations to specify the type of array elements. Without
this field, the API returns errors like:
"GenerateContentRequest.tools[0].function_declarations[2].parameters.properties[fields].items: missing field"

This fix adds the required 'items: { type: 'STRING' }' field for
all array parameters when formatting tools for the Gemini provider.

Changes:
- Modified format_parameters method to add items field for array types
- Added comprehensive unit tests for the fix
- Added integration tests to verify proper tool formatting

This resolves issues when using tools with array parameters in
Gemini models, enabling proper function calling with arrays.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Removed duplicate test coverage by consolidating
tools_array_parameter_handling_spec.rb into tools_spec.rb.
The single test file now comprehensively covers:
- Array parameters with items field
- Mixed parameter types
- Required vs optional parameters
- Integration test of format_tools method
Similar to the Gemini fix, OpenAI also requires an 'items' field
for array-type parameters in tool/function declarations. Without
this field, tools with array parameters may not work correctly.

This commit adds the required 'items: { type: 'string' }' field
for all array-type parameters when formatting tools for OpenAI.

Changes:
- Modified param_schema method to add items field for array types
- Added comprehensive tests for array parameter handling
- Tests verify both single and multiple array parameters work correctly
@finbarr finbarr changed the title Fix Gemini array parameter handling in tool declarations Fix array parameter handling in tool declarations for Gemini and OpenAI Aug 21, 2025
}.compact

# Add items field for array types
property[:items] = { type: 'STRING' } if param.type.to_s.downcase == 'array'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only array type is string?

finbarr and others added 2 commits September 10, 2025 11:17
Previously, array parameters in tool declarations only supported string
item types. This was limiting for tools that needed arrays of numbers,
booleans, objects, or other types.

Changes:
- Add item_type parameter to RubyLLM::Parameter class
- Update OpenAI provider to use item_type for array parameters
- Update Gemini provider to use item_type with proper type mapping
- Add comprehensive tests for different array item types

This enables tools to declare arrays with specific item types:
- Arrays of integers/numbers for numeric data
- Arrays of booleans for flag collections
- Arrays of objects for complex structured data

Addresses feedback from PR crmne#358

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@finbarr
Copy link
Contributor Author

finbarr commented Sep 10, 2025

@crmne Thank you for the feedback! I've updated the implementation to support all array item types, not just strings.

Changes made:

  1. Added item_type parameter to RubyLLM::Parameter class - This allows specifying the type of elements in an array

    param :scores, type: 'array', desc: 'List of scores', item_type: 'integer'
    param :prices, type: 'array', desc: 'List of prices', item_type: 'number'
    param :flags, type: 'array', desc: 'List of flags', item_type: 'boolean'
    param :users, type: 'array', desc: 'List of users', item_type: 'object'
  2. Updated both OpenAI and Gemini providers to use the item_type parameter:

    • OpenAI: Uses lowercase type names (string, number, integer, boolean, object)
    • Gemini: Uses uppercase type names (STRING, NUMBER, BOOLEAN, OBJECT) with proper conversion
    • Both default to string arrays if item_type is not specified (backward compatible)
  3. Added comprehensive tests covering arrays of all supported types

The implementation now properly supports arrays of any JSON Schema type, addressing your concern. The gemfile.lock changes are just platform-specific dependencies (ARM64 Darwin) that were automatically added by bundler.

The PR has been rebased on the latest main branch and all tests are passing.

@crmne
Copy link
Owner

crmne commented Sep 14, 2025

Thank you so much @finbarr! Looking at the DSL though I think it doesn't look very RubyLLM-like. I'm thinking it may be worth rethinking the Tool DSL completely and take inspiration from @danielfriis's excellent RubyLLM::Schema. Could be great for 2.0! I'll think about it.

@finbarr
Copy link
Contributor Author

finbarr commented Sep 14, 2025

@crmne ok sounds good. My company Shogun is using my fork in production to fix the items type bug for now.

As you're thinking about 2.0, one area we've repeatedly run into issues is around observability. It's difficult to get every single raw request/response out of the library right now.

@crmne
Copy link
Owner

crmne commented Sep 14, 2025

@finbarr have you tried message.raw?

@finbarr
Copy link
Contributor Author

finbarr commented Sep 14, 2025

@crmne yes. But we want every single raw request that gets made, and every single raw response that gets received. The hooks and method returns hide failures in the middle, e.g., tool failure retries.

@finbarr
Copy link
Contributor Author

finbarr commented Sep 14, 2025

@crmne it would actually be really nice if there was an easy way to modify requests slightly with an on_before_request or something. This would make it easier to implement tracing with things like langfuse where you need to set trace and span ids.

@crmne
Copy link
Owner

crmne commented Sep 14, 2025

Could be an interesting hook to add! Feel free to open an issue so we can gauge demand

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.

2 participants