openai-go icon indicating copy to clipboard operation
openai-go copied to clipboard

GPT-5 tool calling error

Open AlejandroPerez92 opened this issue 4 months ago • 3 comments

I’m trying to use version v2 of the SDK with the gpt‑5‑nano model, but I’m getting a bad‑request error containing this content:

"metadata" : {
    "raw" : "{\n  \"error\": {\n    \"message\": \"Missing required parameter: 'tools[0].name'.\",\n    \"type\": \"invalid_request_error\",\n    \"param\": \"tools[0].name\",\n    \"code\": \"missing_required_parameter\"\n  }\n}",
    "provider_name" : "OpenAI"
  }

Here’s how I defined the tool:

openai.ChatCompletionFunctionTool(
				openai.FunctionDefinitionParam{
					Name:        "rechazar_mensaje",
					Description: openai.String("Rechazar el mensaje si viola alguna regla"),
				},
			),

This generates the following JSON for the tool:

 "tools" : [ {
    "function" : {
      "name" : "rechazar_mensaje",
      "description" : "Rechazar el mensaje si viola alguna regla"
    },
    "type" : "function"
  }]

I thought this might be unfinished functionality, but I wanted to check if I’m missing something.

AlejandroPerez92 avatar Aug 11 '25 08:08 AlejandroPerez92

Hey @AlejandroPerez92 do you know which release version of the API you're using? I just tried this on the latest release and it worked successfully:

package main

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/openai/openai-go/v2"
)

// This example reproduces GitHub issue #474
// The user reported getting a "Missing required parameter: 'tools[0].name'" error
// when using gpt-5-nano model with tool calling
func main() {
	client := openai.NewClient()
	ctx := context.Background()

	// Reproduce the user's exact code
	params := openai.ChatCompletionNewParams{
		Messages: []openai.ChatCompletionMessageParamUnion{
			openai.UserMessage("Favor de rechazar el siguiente mensaje si viola alguna regla,  como spam o contenido sensible o un error ortográfico: 'Hola, mi number es David. ¿Cómo estás?'"),
		},
		Tools: []openai.ChatCompletionToolUnionParam{
			openai.ChatCompletionFunctionTool(
				openai.FunctionDefinitionParam{
					Name:        "rechazar_mensaje",
					Description: openai.String("Rechazar el mensaje si viola alguna regla"),
				},
			),
		},
		Model: openai.ChatModelGPT5Nano, // Using gpt-5-nano as reported in the issue
	}

	// Print the JSON that would be sent to verify the structure
	toolsJSON, err := json.MarshalIndent(params.Tools, "", "  ")
	if err == nil {
		fmt.Println("Generated tools JSON:")
		fmt.Println(string(toolsJSON))
		fmt.Println()
	}

	// Test the actual API call
	fmt.Println("Making API call...")
	completion, err := client.Chat.Completions.New(ctx, params)
	if err != nil {
		fmt.Printf("Error occurred: %v\n", err)
	} else {
		fmt.Println("✅ Request succeeded!")
		
		choices := completion.Choices
		for i, choice := range choices {
			fmt.Printf("Choice %d:\n", i+1)
			fmt.Printf("  Message: %s\n", choice.Message.Content)
			if len(choice.Message.ToolCalls) > 0 {
				fmt.Printf("  Tool Calls: %+v\n", choice.Message.ToolCalls)
			} else {
				fmt.Println("  No tool calls in this choice")
			}
		}
	}
}
Generated tools JSON:
[
  {
    "function": {
      "name": "rechazar_mensaje",
      "description": "Rechazar el mensaje si viola alguna regla"
    },
    "type": "function"
  }
]

Making API call...
✅ Request succeeded!
Choice 1:
  Message:
  Tool Calls: [{ID:call_6QJL4culAnBoqiMxkhlSgEBc Function:{Arguments:{} Name:rechazar_mensaje JSON:{Arguments:{status:3 raw:"{}"} Name:{status:3 raw:"rechazar_mensaje"} ExtraFields:map[] raw:{
              "name": "rechazar_mensaje",
              "arguments": "{}"
            }}} Type:function Custom:{Input: Name: JSON:{Input:{status:0 raw:} Name:{status:0 raw:} ExtraFields:map[] raw:}} JSON:{ID:{status:3 raw:"call_6QJL4culAnBoqiMxkhlSgEBc"} Function:{status:3 raw:{
              "name": "rechazar_mensaje",
              "arguments": "{}"
            }} Type:{status:3 raw:"function"} Custom:{status:0 raw:} raw:{
            "id": "call_6QJL4culAnBoqiMxkhlSgEBc",
            "type": "function",
            "function": {
              "name": "rechazar_mensaje",
              "arguments": "{}"
            }
          }}}]

dtmeadows avatar Aug 11 '25 16:08 dtmeadows

Not sure, I’m using it through OpenRouter. I’ll try with an OpenAI account later to see if it makes any difference.

Anyway, if you look at the examples on https://platform.openai.com/docs/guides/function-calling?lang=javascript, the structure is different, the "function" child is at the root level.

AlejandroPerez92 avatar Aug 11 '25 17:08 AlejandroPerez92

Yes I can confirm that using the OpenAI API is working well 🤔

AlejandroPerez92 avatar Aug 11 '25 19:08 AlejandroPerez92