Skip to content

Under the gpt5 model, the completion interface cannot utilize the custom tool's large capability #2667

Description

@NiceCode666

Confirm this is an issue with the Python library and not an underlying OpenAI API

  • This is an issue with the Python library

Describe the bug

Under the gpt5 model, the completion interface cannot utilize the custom tool's large capability

I have confirmed multiple times that my format meets the API interface requirements, and the API interface is: https://platform.openai.com/docs/api-reference/chat/create#chat -create-tools-custom-tool-custom-format

The interface response result is: Error code: 400 - {'error': {'message': 'Invalid param', 'type': 'invalid_request_error', 'param': 'c44c810b-15b6-4c62-8e6d-1b8ee2ceece8', 'code': 'param_error'}}
But it is unclear which field is the problem and how to fix it. Please provide the correct usage method

To Reproduce

Run the code

Code snippets

definition = """
start: expr
expr: term (SP ADD SP term)* -> add
| term
term: factor (SP MUL SP factor)* -> mul
| factor
factor: INT
SP: " "
ADD: "+"
MUL: "*"
%import common.INT
"""

ebnf_description = "Creates valid Lark grammar."

def custom_tool_ebnf_grammar_1():
    return {
                "type": "custom",
                "custom": {
                    "name": "ebnf_grammar",
                    "description": ebnf_description,
                    "format": {
                        "type": "grammar",
                        "grammar": {
                            "syntax": "lark",
                            "definition": definition,
                        }
                    },
                }
            }

def custom_tool_ebnf_grammar_2():
    return {
                "type": "custom",
                "custom": {
                    "name": "ebnf_grammar",
                    "description": ebnf_description,
                    "format": {
                        "type": "grammar",
                        "syntax": "lark",
                        "definition": definition,
                    },
                }
            }


def custom_tool_ebnf_grammar_3():
    return {
            "type": "custom",
            "name": "ebnf_grammar",
            "description": ebnf_description,
            "format": {
                "type": "grammar",
                "syntax": "lark",
                "definition": definition,
            },
        }

client = OpenAI()

ebnf_query = "use the ebnf_grammar tool to add four plus four."

def test_completion_chat_ebnf_grammar_1():
    print("===== start test_completion_chat_ebnf_grammar_1 ===== ")
    response = client.chat.completions.create(
        model="gpt-5",
        messages=[{"role": "user", "content": ebnf_query}],
        tools=[custom_tool_ebnf_grammar_1()],
        parallel_tool_calls=False,
        tool_choice="required"
    )
    print(response.choices[0].message.content)
    print("===== end test_completion_chat_ebnf_grammar_1 ===== ")

def test_completion_chat_ebnf_grammar_2():
    print("===== start test_completion_chat_ebnf_grammar_2 ===== ")
    response = client.chat.completions.create(
        model="gpt-5",
        messages=[{"role": "user", "content": ebnf_query}],
        tools=[custom_tool_ebnf_grammar_2()],
        parallel_tool_calls=False,
        tool_choice="required"
    )
    print(response.choices[0].message.content)
    print("===== end test_completion_chat_ebnf_grammar_2 ===== ")


def test_completion_chat_ebnf_grammar_3():
    print("===== start test_completion_chat_ebnf_grammar_3 ===== ")
    response = client.chat.completions.create(
        model="gpt-5",
        messages=[{"role": "user", "content": ebnf_query}],
        tools=[custom_tool_ebnf_grammar_3()],
        parallel_tool_calls=False,
        tool_choice="required"
    )
    print(response.choices[0].message.content)
    print("===== end test_completion_chat_ebnf_grammar_3 ===== ")

OS

macOS

Python version

Python 3.9

Library version

openai 1.108.1

Activity

  1. thromel commented on Dec 4, 2025

    @thromel

    Thank you for reporting this issue. I've identified a bug in the library's type definitions for custom tools in the Chat Completions API.

    The Problem

    The ChatCompletionCustomToolParam type had incorrect nesting that didn't match the actual API structure. According to the official documentation, custom tools should use this flat structure:

    {
        "type": "custom",
        "name": "tool_name",
        "description": "Tool description",
        "format": {
            "type": "grammar",
            "syntax": "lark",
            "definition": grammar_definition
        }
    }

    But the library's type definitions incorrectly expected extra nesting:

    • name, description, format were expected inside a custom object
    • syntax, definition were expected inside a format.grammar object

    The Correct Format

    Based on your examples, custom_tool_ebnf_grammar_3() has the correct structure (closest to the API spec):

    def custom_tool_ebnf_grammar_3():
        return {
            "type": "custom",
            "name": "ebnf_grammar",
            "description": ebnf_description,
            "format": {
                "type": "grammar",
                "syntax": "lark",
                "definition": definition,
            },
        }

    This matches the Responses API's CustomToolParam structure, which is correct.

    Fix

    The ChatCompletionCustomToolParam type definition needs to be updated to match the CustomToolParam structure from the Responses API (which has the correct format). The fix is to remove the extra nesting in src/openai/types/chat/chat_completion_custom_tool_param.py.

    Note: The "Invalid param" error with a UUID in the param field suggests the actual validation error is happening on the API side. If custom_tool_ebnf_grammar_3() is still failing, there may be additional constraints on the grammar definition itself - try a simpler grammar to rule out grammar parsing issues.

  2. RobertCraigie commented on Dec 4, 2025

    @RobertCraigie
    Contributor

    I think the issue is trying to access message content instead of tool calls?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions