-
Notifications
You must be signed in to change notification settings - Fork 29
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
base: trunk
Are you sure you want to change the base?
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_calls
array 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(); |
Copilot uses AI. Check for mistakes.
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).
$functionCall = new FunctionCall( | ||
'call_1', | ||
'list_capabilities', | ||
[] // Empty arguments 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.
See my above comment, the problem is in PHP it's undefined whether this is an empty associative array (object
in JSON schema) or an empty indexed/numeric array (array
in JSON schema). Just to clarify what I meant above.
|
||
$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); | |
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_calls
field 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 item
tool_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