Bug Description
When a tool input model contains a Pydantic discriminated union, build_strict_openai_schema(...) emits oneOf in the generated schema.
That appears to be incompatible with OpenAI strict tool schemas. The resulting tool registration fails with:
Invalid schema for function '<function>': In context=(), 'oneOf' is not permitted.
The same union without an explicit discriminator produces anyOf instead and works.
Expected Behavior
to_strict_json_schema(...) should normalize discriminated unions into a strict-mode-compatible schema shape:
https://github.com/livekit/agents/blob/main/livekit-agents/livekit/agents/llm/_strict.py
Reproduction Steps
from typing import Annotated, Literal
from pydantic import BaseModel, Field
class Car(BaseModel):
vehicle: Literal["Car"]
brand: str
color: str
class Bike(BaseModel):
vehicle: Literal["Bike"]
brand: str
color: str
type CarOrBike = Annotated[Car | Bike, Field(discriminator="vehicle")]
# type CarOrBike = Annotated[Car | Bike, Field()] # this version works
and then use `CarOrBike` in a `@function_tool` parameter.
Relevant schema difference:
With discriminator:
{
"$defs": {
"CarOrBike": {
"oneOf": [
{ "$ref": "#/$defs/Car" },
{ "$ref": "#/$defs/Bike" }
]
}
}
}
Without discriminator:
{
"$defs": {
"CarOrBike": {
"anyOf": [
{ "$ref": "#/$defs/Car" },
{ "$ref": "#/$defs/Bike" }
]
}
}
}
Operating System
macOS/Linux
Models Used
OpenAI GPT 4.1, should occur with any OpenAI model with strict mode enabled
Package Versions
Session/Room/Call IDs
N/A
Proposed Solution
Normalize `oneOf` back to `anyOf` when building the strict OpenAI schema.
Additional Context
Discriminated unions are the recommended Pydantic shape for tagged unions:
https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions
Screenshots and Recordings
No response
Bug Description
When a tool input model contains a Pydantic discriminated union,
build_strict_openai_schema(...)emitsoneOfin the generated schema.That appears to be incompatible with OpenAI strict tool schemas. The resulting tool registration fails with:
The same union without an explicit discriminator produces
anyOfinstead and works.Expected Behavior
to_strict_json_schema(...)should normalize discriminated unions into a strict-mode-compatible schema shape:https://github.com/livekit/agents/blob/main/livekit-agents/livekit/agents/llm/_strict.py
Reproduction Steps
from typing import Annotated, Literal from pydantic import BaseModel, Field class Car(BaseModel): vehicle: Literal["Car"] brand: str color: str class Bike(BaseModel): vehicle: Literal["Bike"] brand: str color: str type CarOrBike = Annotated[Car | Bike, Field(discriminator="vehicle")] # type CarOrBike = Annotated[Car | Bike, Field()] # this version works and then use `CarOrBike` in a `@function_tool` parameter. Relevant schema difference: With discriminator: { "$defs": { "CarOrBike": { "oneOf": [ { "$ref": "#/$defs/Car" }, { "$ref": "#/$defs/Bike" } ] } } } Without discriminator: { "$defs": { "CarOrBike": { "anyOf": [ { "$ref": "#/$defs/Car" }, { "$ref": "#/$defs/Bike" } ] } } }Operating System
macOS/Linux
Models Used
OpenAI GPT 4.1, should occur with any OpenAI model with strict mode enabled
Package Versions
Session/Room/Call IDs
N/A
Proposed Solution
Additional Context
Discriminated unions are the recommended Pydantic shape for tagged unions:
https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions
Screenshots and Recordings
No response