Skip to content

fix(llm, tool): Send open-object schemas unstrict - #1208

Open
JeanMertz wants to merge 1 commit into
mainfrom
tool-openai
Open

JeanMertz wants to merge 1 commit into
mainfrom
tool-openai

Conversation

@JeanMertz

Copy link
Copy Markdown
Collaborator

A tool parameter declared as a free-form object (type = "object" with no properties, or properties = {}) no longer gets the whole request rejected by OpenAI with Invalid schema for function ...: Extra required key 'body' supplied. Strict mode requires every object to be closed with a fixed set of keys, and a free-form object or a map type (one that sets additionalProperties to true or to a schema) cannot be expressed that way. JP used to close such objects anyway, which either failed the request or left the model able to send only {} and silently dropped a map type's extra keys.

Tools with an open object are now sent with strict: false on OpenAI, OpenRouter, the OpenAI-compatible providers (llama.cpp, vLLM), and Anthropic, with the schema passed through as declared. Structured output follows the same rule on OpenAI, OpenRouter and Cerebras. Anthropic has no unconstrained structured output mode, so a --schema containing an open object is refused with a clear error instead of being answered with {}.

The check also follows anyOf, oneOf and allOf branches. A nullable free-form object (Optional[dict]) is detected as open, while a nullable typed object (Optional[Model]) no longer knocks its tool out of strict mode just because the wrapper declares no type of its own.

A tool parameter declared as a free-form object (`type = "object"` with
no `properties`, or `properties = {}`) no longer gets the whole request
rejected by OpenAI with `Invalid schema for function ...: Extra required
key 'body' supplied`. Strict mode requires every object to be closed with
a fixed set of keys, and a free-form object or a map type (one that sets
`additionalProperties` to `true` or to a schema) cannot be expressed that
way. JP used to close such objects anyway, which either failed the
request or left the model able to send only `{}` and silently dropped a
map type's extra keys.

Tools with an open object are now sent with `strict: false` on OpenAI,
OpenRouter, the OpenAI-compatible providers (llama.cpp, vLLM), and
Anthropic, with the schema passed through as declared. Structured output
follows the same rule on OpenAI, OpenRouter and Cerebras. Anthropic has
no unconstrained structured output mode, so a `--schema` containing an
open object is refused with a clear error instead of being answered with
`{}`.

The check also follows `anyOf`, `oneOf` and `allOf` branches. A nullable
free-form object (`Optional[dict]`) is detected as open, while a
nullable typed object (`Optional[Model]`) no longer knocks its tool out
of strict mode just because the wrapper declares no `type` of its own.

Signed-off-by: Jean Mertz <git@jeanmertz.com>

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant