[GH-ISSUE #13472] Nested objects properties silently removed from tooling requests #70949

Closed
opened 2026-05-04 23:33:13 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @du291 on GitHub (Dec 14, 2025).
Original GitHub issue: https://github.com/ollama/ollama/issues/13472

What is the issue?

When a tool call contains functions that have further objects as their arguments, the properties of these functions are silently removed. This behavior is undocumented, does not throw an error or warning to indicate an unsupported feature. The consequence is that the LLM will infer the most probable properties to fill in, often wrongly.

As a secondary issue, the information whether nested objects are supported or not in this made-up "tool schema" is hard to find, the documentation itself is incomplete to indicate whether this is an actual thing or not.

Suggested fix: If nested objects are supported, please offer proper guidance in the documentation. If they aren't, refuse API calls that use them (fail fast).

Relevant log output

This request proves that the LLM can press the correct button when asked to (i.e. the reported problem is not an inference problem).

POST /api/chat HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Content-Length: 756
Content-Type: application/json
Host: localhost:11434
User-Agent: HTTPie/3.2.4

{
    "messages": [
        {
            "content": "Press the button number two",
            "role": "user"
        }
    ],
    "model": "qwen3:latest",
    "stream": false,
    "think": false,
    "tools": [
        {
            "function": {
                "description": "",
                "name": "press_button",
                "parameters": {
                    "properties": {
                        "description": {
                            "description": "Summary in English",
                            "type": "string"
                        },
                        "number_one": {
                            "description": "button number one pressed yes/no",
                            "type": "string"
                        },
                        "number_two": {
                            "description": "button number two pressed yes/no",
                            "type": "string"
                        }
                    },
                    "required": [
                        "number_one",
                        "number_two",
                        "description"
                    ],
                    "type": "object"
                }
            },
            "type": "function"
        }
    ]
}
       

HTTP/1.1 200 OK
Content-Length: 486
Content-Type: application/json; charset=utf-8
Date: Sun, 14 Dec 2025 09:42:49 GMT

{
    "created_at": "2025-12-14T09:42:49.35235023Z",
    "done": true,
    "done_reason": "stop",
    "eval_count": 38,
    "eval_duration": 48528601370,
    "load_duration": 1493108459,
    "message": {
        "content": "",
        "role": "assistant",
        "tool_calls": [
            {
                "function": {
                    "arguments": {
                        "description": "Button number two is pressed",
                        "number_one": "no",
                        "number_two": "yes"
                    },
                    "index": 0,
                    "name": "press_button"
                },
                "id": "call_bovfcq91"
            }
        ]
    },
    "model": "qwen3:latest",
    "prompt_eval_count": 182,
    "prompt_eval_duration": 209152034949,
    "total_duration": 259229107590
}

Now, if we add a nested object to the tooling schema (there's no precise documentation on how to do this, so I am guessing from available sources on the net):

POST /api/chat HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Content-Length: 1018
Content-Type: application/json
Host: localhost:11434
User-Agent: HTTPie/3.2.4

{
    "messages": [
        {
            "content": "Press the button number two",
            "role": "user"
        }
    ],
    "model": "qwen3:latest",
    "stream": false,
    "think": false,
    "tools": [
        {
            "function": {
                "description": "",
                "name": "press_button",
                "parameters": {
                    "properties": {
                        "button_press": {
                            "description": "Press a button",
                            "properties": {
                                "number_one": {
                                    "description": "button number one pressed yes/no",
                                    "type": "string"
                                },
                                "number_two": {
                                    "description": "button number two pressed yes/no",
                                    "type": "string"
                                }
                            },
                            "required": [
                                "number_one",
                                "number_two"
                            ],
                            "type": "object"
                        },
                        "description": {
                            "description": "Summary in English",
                            "type": "string"
                        }
                    },
                    "required": [
                        "button_press",
                        "description"
                    ],
                    "type": "object"
                }
            },
            "type": "function"
        }
    ]
}


HTTP/1.1 200 OK
Content-Length: 472
Content-Type: application/json; charset=utf-8
Date: Sun, 14 Dec 2025 09:45:29 GMT

{
    "created_at": "2025-12-14T09:45:29.480262482Z",
    "done": true,
    "done_reason": "stop",
    "eval_count": 33,
    "eval_duration": 41955499882,
    "load_duration": 220830774,
    "message": {
        "content": "",
        "role": "assistant",
        "tool_calls": [
            {
                "function": {
                    "arguments": {
                        "button_press": {
                            "button": 2
                        },
                        "description": "Press the second button"
                    },
                    "index": 0,
                    "name": "press_button"
                },
                "id": "call_4bkavug1"
            }
        ]
    },
    "model": "qwen3:latest",
    "prompt_eval_count": 160,
    "prompt_eval_duration": 117600181805,
    "total_duration": 159795188168
}

The LLM does not respect the nested object schema, because it's not aware of it. If we look at the prompts using OLLAMA_DEBUG=2, we can see that the properties content of the button_press object has been removed by ollama (i.e. number_one and number_two aren't in the prompt).

# Tools

You may call one or more functions to assist with the user query.

You are provided with function signatures within <tools></tools> XML tags:
<tools>
{"type": "function", "function": {"name":"press_button","parameters":{"type":"object","required":["button_press","description"],"properties":{"button_press":{"type":"object","description":"Press a button"},"description":{"type":"string","description":"Summary in English"}}}}}
</tools>

For each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:
<tool_call>
{"name": <function-name>, "arguments": <args-json-object>}
</tool_call><|im_end|>
<|im_start|>user
Press the button number two /no_think<|im_end|>
<|im_start|>assistant
<think>

</think>

OS

Linux

GPU

Nvidia

CPU

Intel

Ollama version

0.13.3

Originally created by @du291 on GitHub (Dec 14, 2025). Original GitHub issue: https://github.com/ollama/ollama/issues/13472 ### What is the issue? When a tool call contains functions that have further objects as their arguments, the properties of these functions are silently removed. This behavior is undocumented, does not throw an error or warning to indicate an unsupported feature. The consequence is that the LLM will infer the most probable properties to fill in, often wrongly. As a secondary issue, the information whether nested objects are supported or not in this made-up "tool schema" is hard to find, the documentation itself is incomplete to indicate whether this is an actual thing or not. Suggested fix: If nested objects are supported, please offer proper guidance in the documentation. If they aren't, refuse API calls that use them (fail fast). ### Relevant log output This request proves that the LLM can press the correct button when asked to (i.e. the reported problem is not an inference problem). ``` POST /api/chat HTTP/1.1 Accept: application/json, */*;q=0.5 Accept-Encoding: gzip, deflate, br, zstd Connection: keep-alive Content-Length: 756 Content-Type: application/json Host: localhost:11434 User-Agent: HTTPie/3.2.4 { "messages": [ { "content": "Press the button number two", "role": "user" } ], "model": "qwen3:latest", "stream": false, "think": false, "tools": [ { "function": { "description": "", "name": "press_button", "parameters": { "properties": { "description": { "description": "Summary in English", "type": "string" }, "number_one": { "description": "button number one pressed yes/no", "type": "string" }, "number_two": { "description": "button number two pressed yes/no", "type": "string" } }, "required": [ "number_one", "number_two", "description" ], "type": "object" } }, "type": "function" } ] } HTTP/1.1 200 OK Content-Length: 486 Content-Type: application/json; charset=utf-8 Date: Sun, 14 Dec 2025 09:42:49 GMT { "created_at": "2025-12-14T09:42:49.35235023Z", "done": true, "done_reason": "stop", "eval_count": 38, "eval_duration": 48528601370, "load_duration": 1493108459, "message": { "content": "", "role": "assistant", "tool_calls": [ { "function": { "arguments": { "description": "Button number two is pressed", "number_one": "no", "number_two": "yes" }, "index": 0, "name": "press_button" }, "id": "call_bovfcq91" } ] }, "model": "qwen3:latest", "prompt_eval_count": 182, "prompt_eval_duration": 209152034949, "total_duration": 259229107590 } ``` Now, if we add a nested object to the tooling schema (there's no precise documentation on how to do this, so I am guessing from available sources on the net): ``` POST /api/chat HTTP/1.1 Accept: application/json, */*;q=0.5 Accept-Encoding: gzip, deflate, br, zstd Connection: keep-alive Content-Length: 1018 Content-Type: application/json Host: localhost:11434 User-Agent: HTTPie/3.2.4 { "messages": [ { "content": "Press the button number two", "role": "user" } ], "model": "qwen3:latest", "stream": false, "think": false, "tools": [ { "function": { "description": "", "name": "press_button", "parameters": { "properties": { "button_press": { "description": "Press a button", "properties": { "number_one": { "description": "button number one pressed yes/no", "type": "string" }, "number_two": { "description": "button number two pressed yes/no", "type": "string" } }, "required": [ "number_one", "number_two" ], "type": "object" }, "description": { "description": "Summary in English", "type": "string" } }, "required": [ "button_press", "description" ], "type": "object" } }, "type": "function" } ] } HTTP/1.1 200 OK Content-Length: 472 Content-Type: application/json; charset=utf-8 Date: Sun, 14 Dec 2025 09:45:29 GMT { "created_at": "2025-12-14T09:45:29.480262482Z", "done": true, "done_reason": "stop", "eval_count": 33, "eval_duration": 41955499882, "load_duration": 220830774, "message": { "content": "", "role": "assistant", "tool_calls": [ { "function": { "arguments": { "button_press": { "button": 2 }, "description": "Press the second button" }, "index": 0, "name": "press_button" }, "id": "call_4bkavug1" } ] }, "model": "qwen3:latest", "prompt_eval_count": 160, "prompt_eval_duration": 117600181805, "total_duration": 159795188168 } ``` The LLM does not respect the nested object schema, because it's not aware of it. If we look at the prompts using OLLAMA_DEBUG=2, we can see that the `properties` content of the `button_press` object has been removed by ollama (i.e. `number_one` and `number_two` aren't in the prompt). ``` # Tools You may call one or more functions to assist with the user query. You are provided with function signatures within <tools></tools> XML tags: <tools> {"type": "function", "function": {"name":"press_button","parameters":{"type":"object","required":["button_press","description"],"properties":{"button_press":{"type":"object","description":"Press a button"},"description":{"type":"string","description":"Summary in English"}}}}} </tools> For each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags: <tool_call> {"name": <function-name>, "arguments": <args-json-object>} </tool_call><|im_end|> <|im_start|>user Press the button number two /no_think<|im_end|> <|im_start|>assistant <think> </think> ``` ### OS Linux ### GPU Nvidia ### CPU Intel ### Ollama version 0.13.3
GiteaMirror added the bug label 2026-05-04 23:33:13 -05:00
Author
Owner

@rick-github commented on GitHub (Dec 14, 2025):

#6155

<!-- gh-comment-id:3650652956 --> @rick-github commented on GitHub (Dec 14, 2025): #6155
Author
Owner

@ParthSareen commented on GitHub (Dec 17, 2025):

Closed with https://github.com/ollama/ollama/pull/13508

<!-- gh-comment-id:3666935427 --> @ParthSareen commented on GitHub (Dec 17, 2025): Closed with https://github.com/ollama/ollama/pull/13508
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/ollama#70949