---
type: email
from: gn00295120 <notifications@github.com>
subject: Re: [openai/openai-agents-python] litellm + streaming + tool_choice =

 'mytool' fails with pydantic error (Issue #1846)
received: 2026-03-06 08:08:19
date_header: Sat, 18 Oct 2025 11:31:33 -0700
priority: normal
status: awaiting_approval
uid: 32938
---

## Email Content

**From:** gn00295120 <notifications@github.com>
**Subject:** Re: [openai/openai-agents-python] litellm + streaming + tool_choice =

 'mytool' fails with pydantic error (Issue #1846)
**Date:** Sat, 18 Oct 2025 11:31:33 -0700

### Body (preview)

gn00295120 left a comment (openai/openai-agents-python#1846)



Hi @andysalerno! 👋



Great news - this issue has been fixed in PR #1929!



## Root Cause



You identified the problem exactly! The code was incorrectly casting `tool_choice` to only accept `Literal["auto", "required", "none"]`, but the OpenAI Responses API actually accepts specific tool names via the `ToolChoiceFunction` type.



The converter was already creating the right format, but the streaming code wasn't handling it properly.



## What Was Fixed



PR #1929 completely rewrites the `tool_choice` conversion logic in `litellm_model.py`:



### Before (Broken):

```python

tool_choice=cast(Literal["auto", "required", "none"], tool_choice)

```



### After (Fixed):

```python

# Convert tool_choice to the correct type for Response

response_tool_choice: Literal["auto", "required", "none"] | ToolChoiceFunction

if tool_choice is omit:

    response_tool_choice = "auto"

elif isinstance(tool_choice, ToolChoiceFunction):

    # Already a ToolChoiceFunction, use directly

    response_tool_choice = tool_choice

elif isinstance(tool_choice, dict):

    # Convert from Responses format dict to ToolChoiceFunction

    # The Responses Converter returns: {"type": "function", "name": "tool_name"}

    tool_name = tool_choice.get("name")

    if (...):

        response_tool_choice = ToolChoiceFunction(type="function", name=tool_name)

    else:

        response_tool_choice = "auto"

elif tool_choice in ("auto", "required", "none"):

    response_tool_choice = cast(Literal["auto", "required", "none"], tool_choice)

else:

    response_tool_choice = "auto"

```



## Now Your Code Works!



```python

agent = Agent(

    name="RespondingAgent",

    tools=tools,

    model_settings=ModelSettings(

        tool_choice="reason"  # ✅ This now works with LiteLLM streaming!

    ),

)

```



The specific tool name will be properly preserved in the `Response.tool_choice` field, so the LLM will be forced to call y

---

## Suggested Actions
- [ ] Reply
- [ ] Archive
- [ ] Escalate
