- 
                Notifications
    You must be signed in to change notification settings 
- Fork 34
Fix empty tool calls and arguments in OpenAI compatible models #80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Only include tool_calls field when there are actual tool calls (OpenAI rejects empty arrays) - Convert empty argument arrays to objects in JSON encoding (both OpenAI and Anthropic require objects) - Add comprehensive test coverage for both edge cases This fixes critical API failures when AI models make function/tool calls with no parameters, making the SDK production-ready for parameterless functions like those in WordPress Abilities API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes critical compatibility issues with OpenAI and Anthropic APIs when AI models make function/tool calls with empty parameters. The changes ensure proper JSON encoding and conditional field inclusion to prevent API rejections.
- Fix empty tool_callsarray handling by only including the field when non-empty
- Fix empty arguments encoding to produce {}instead of[]for parameterless function calls
- Add comprehensive test coverage for both edge cases
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description | 
|---|---|
| src/Providers/OpenAiCompatibleImplementation/AbstractOpenAiCompatibleTextGenerationModel.php | Implements conditional tool_calls inclusion and empty arguments object conversion | 
| tests/unit/Providers/OpenAiCompatibleImplementation/AbstractOpenAiCompatibleTextGenerationModelTest.php | Adds test cases for empty tool calls and empty arguments scenarios | 
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| if (is_array($args) && empty($args)) { | ||
| $args = (object) array(); | 
    
      
    
      Copilot
AI
    
    
    
      Sep 2, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The (object) array() conversion can be simplified to new \stdClass() for better readability and clarity of intent when creating an empty object.
| if (is_array($args) && empty($args)) { | |
| $args = (object) array(); | |
| $args = new \stdClass(); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Jameswlepage Thanks, great catch!
For the empty tool_calls, this makes total sense. About the other change, I have a follow up question - technically always making it an empty object doesn't seem right (unless this is truly the only way to make it work against the OpenAI API).
| if (is_array($args) && empty($args)) { | ||
| $args = (object) array(); | ||
| } | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is tricky. Technically speaking, for JSON-encoding this should still only be turned into stdClass when the expected input shape is object. While that's often the case, it only depends on the schema - it could also be array, in which case leaving it a PHP array would be correct.
What happens if the parameters JSON schema specified for the function expects an actual array (indexed/numeric)? Does the OpenAI API always fail if it's an empty array? If so, that would seem like a flaw in the API (although, if that's the case, of course we still need to fix / work around it in our SDK).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about this a bit more, and while my concern is still valid in theory, in practice the OpenAI API specification does not support arrays as the root value. So it's fair to assume the data should be an object in this scenario.
        
          
                ...Providers/OpenAiCompatibleImplementation/AbstractOpenAiCompatibleTextGenerationModelTest.php
          
            Show resolved
            Hide resolved
        
      |  | ||
| $model = $this->createModel(); | ||
| $prepared = $model->exposePrepareMessagesParam([$message], null); | ||
|  | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PHPCS errors here:
| $model = $this->createModel(); | |
| $prepared = $model->exposePrepareMessagesParam([$message], null); | |
| $model = $this->createModel(); | |
| $prepared = $model->exposePrepareMessagesParam([$message], null); | |
| The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the  If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Jameswlepage It's been a while, so I hope it's fine that I finished this up for you! It was only a few minor details anyway.
Hoping to get 0.2.0 out by end of this week, it's long overdue!
Summary
Fixes critical API compatibility issues when AI models make function/tool calls with no parameters. The SDK was generating invalid payloads rejected by OpenAI and Anthropic APIs.
Changes
tool_callsfield when array contains items (OpenAI rejects empty arrays){}not[]for empty parameters)Technical Details
The issue manifests in two ways:
OpenAI API Error:
Invalid 'messages[X].tool_calls': empty array. Expected at least one itemtool_calls: []is included in messagesAnthropic API Error:
messages.X.content.0.tool_use.input: Input should be a valid dictionary"[]"instead of"{}"Testing
Impact
Related