Tool def with a plain object JSON schema causes api error

I have a function with a parameter of dictionary type (with untyped key and value). This is what the tool definition looks like

{
    "type": "function",
    "function": {
        "name": "example_fn",
        "strict": True,
        "parameters": {
            "properties": {
                "param_1": {
                    "title": "Param 1",
                    "type": "object",
                    "additionalProperties": False,
                }
            },
            "title": "example_fn",
            "type": "object",
            "additionalProperties": False,
            "required": ["param_1"],
        },
        "description": "example_fn",
    },
}

however, if I pass this to the api call, i get the error

BadRequestError: Error code: 400 - {'error': {'message': "Invalid schema for function 'example_fn': In context=(), 'required' is required to be supplied and to be an array including every key in properties. Extra required key 'param_1' supplied.", 'type': 'invalid_request_error', 'param': 'tools[0].function.parameters', 'code': 'invalid_function_parameters'}}

I believe this happens because the JSON schema of an object without any defined properties (like the one right below) is unsupported, even though the docs make no mention of this

               {
                    "title": "Param 1",
                    "type": "object",
                    "additionalProperties": False,
                }

In fact, even if I tried to further type the dictionary, like this tool def

{
    "type": "function",
    "function": {
        "name": "example_fn",
        "strict": True,
        "parameters": {
            "properties": {
                "param_1": {
                    "title": "Param 1",
                    "type": "object",
                    'additionalProperties': {'type': 'integer'},
                }
            },
            "title": "example_fn",
            "type": "object",
            "additionalProperties": False,
            "required": ["param_1"],
        },
        "description": "example_fn",
    },
}

It still gets rejected by the api and throws the same error.

The only workaround is to actually leave an empty “required”

{
    "type": "function",
    "function": {
        "name": "example_fn",
        "strict": True,
        "parameters": {
            "properties": {
                "param_1": {
                    "title": "Param 1",
                    "type": "object",
                    "additionalProperties": False,
                }
            },
            "title": "example_fn",
            "type": "object",
            "additionalProperties": False,
            "required": [],
        },
        "description": "example_fn",
    },
}

which is puzzling because the docs clearly state that “required” must include all the fields.

Please let me know if this is a bug or expected behavior

What do you expect the AI to emit to a function? This is incorrigible. There is no data type such as string to be written.

Start at something that can actually produce a response.

{
  "name": "example_fn",
  "description": "Produces a value for param_1",
  "strict": true,
  "parameters": {
    "type": "object",
    "required": [
      "param_1"
    ],
    "properties": {
      "param_1": {
        "type": "string",
        "description": "The value to be emitted by the function"
      }
    },
    "additionalProperties": false
  }
}
1 Like

@_j you realize that this issue will occur with any dictionary parameter of the form e.g. param1: Dict[str, int]? Whether this is good practice or not is a different questions (and I agree that you should avoid Dict type parameters), but there are times when I need to quickly test something and the expected dictionary arg is extremely obvious from the system prompt, function description, and conversation context.

The AI is not provided “write whatever function you want”. It has specific keys and key value types given to it for the function in the specification.

You cannot have arbitrary AI made-up key names in an object. You can however have what you describe with “number” JSON data type - this AI that can load its own functions, for example.

1 Like

“You cannot have arbitrary AI made-up key names in an object”: where is this stated in the documentation? Plus, i’ve already told you that im dealing with a python dictionary (including one where both the key and value are type annotated), not with “arbitrary object”.

As I said, whether this is good practice or not is a different question. In fact, when I use the same tool definition in an anthropic claude api call, the model is able to pass the right dict arg to the function call.

Besides a year of documentation and forum examples, you can just observe how the properties of a function are placed into AI context. I have a write-up here where you can see the translation of JSON keys into AI’s language specification of how to send to functions.

Understanding how the function specification is actually employed and understood by the AI will help you along, in making schemas that can be even accepted by the OpenAI API.

Python openai library sends JSON, and the API accepts JSON, which is translated from your streamable python object.

2 Likes

but what im saying is that the following is completely valid JSON schema

               {
                    "title": "Param 1",
                    "type": "object",
                    "additionalProperties": False,
                }

and nowhere in the docs it is stated that such JSON schema is unaccepted

nowhere?

Function calling with Structured Outputs supports a subset of the JSON Schema language.

https://platform.openai.com/docs/guides/structured-outputs#supported-schemas

1 Like

@_j im aware of that documentation. Do you see it explicitly stating that an “empty object” type json schema is unsupported? I dont, so that’s why Im seeking clarity in this forum.

@_j: you have been talking in circles

If it doesn’t work like you wish, then you need to understand and adapt.

The whole point of structured outputs is that the AI can only write JSON output that can be parsed and validated by key. No keys can be made optional (thus you also manually place every data field in “required” or get denied, to reinforce your own understanding), and no objects can grow dynamically with new or unspecified keys.

You can use “strict”: false, and then only the AI’s understanding of the passed schema is a limit.

You can wish for more documentation to be spoon-fed to you - but there are already cookbook examples and tons of forum advice.

In some cases, you can have a completely empty object, devoid of pointless “title” etc, if you want a function call schema to just be a trigger, for example.

1 Like

@_j bruh, im simply asking if it is currently explicitly supported or not, since the docs are unclear. A simple yes or no answer. Im not asking for it to be supported per se. You have been incredibly unhelpful and spamming my post, so please go away

I’ll make sure my assistance never crosses paths with you again. Good luck in your future silent endeavors!

Add a “description” for each field in the properties.