Skip to content

openai_supports_tool_choice_required=False is still setting tool_choice to required for Responses #3270

@pamelafox

Description

@pamelafox

Initial Checks

Description

This is another issue with gpt-oss on NIM (vLLM) with Responses API. I'm getting an error that tool_choice must be 'auto' for Harmony Responses:

pydantic_ai.exceptions.ModelHTTPError: status_code: 400, model_name: openai/gpt-oss-20b, body: {'message': "Only 'auto' tool_choice is supported in response API with Harmony None", 'type': 'BadRequestError', 'param': None, 'code': 400}

I've tried setting openai_supports_tool_choice_required=False but that isn't changing the tool_choice in the request to 'auto' as I hoped. I wonder if maybe it's not implemented for Responses API?

Full code here:

import asyncio
import os
import random
import logging
from typing import Literal

from dotenv import load_dotenv
from openai import AsyncOpenAI
from pydantic import BaseModel
from pydantic_ai import Agent, RunContext
from pydantic_ai.models.openai import OpenAIResponsesModel
from pydantic_ai.profiles.openai import OpenAIModelProfile
from pydantic_ai.providers.openai import OpenAIProvider
from rich.logging import RichHandler

load_dotenv(override=True)
logging.basicConfig(level=logging.DEBUG, format="%(message)s", datefmt="[%X]", handlers=[RichHandler()])
logger = logging.getLogger(__name__)

client = AsyncOpenAI(
    base_url=os.environ["NIM_ENDPOINT"],
    api_key="none")

model = OpenAIResponsesModel(
    os.environ['NIM_MODEL'],
    provider=OpenAIProvider(openai_client=client),
    profile=OpenAIModelProfile(openai_responses_requires_function_call_status_none=True, openai_supports_tool_choice_required=False),
)

class Weather(BaseModel):
    city: str
    temperature: int
    wind_speed: int
    rain_chance: int


class TriageResult(BaseModel):
    language: Literal["spanish", "english"]
    reason: str


async def get_weather(ctx: RunContext[None], city: str) -> Weather:
    """Returns weather data for the given city."""
    temp = random.randint(50, 90)
    wind_speed = random.randint(5, 20)
    rain_chance = random.randint(0, 100)
    return Weather(city=city, temperature=temp, wind_speed=wind_speed, rain_chance=rain_chance)


spanish_weather_agent = Agent(
    model,
    tools=[get_weather],
    system_prompt=("Eres un agente del clima. Solo respondes en español con información del tiempo para la ciudad pedida. " "Usa la herramienta 'get_weather' para obtener datos. Devuelve una respuesta breve y clara."),
)

english_weather_agent = Agent(
    model,
    tools=[get_weather],
    system_prompt=("You are a weather agent. You only respond in English with weather info for the requested city. " "Use the 'get_weather' tool to fetch data. Keep responses concise."),
)


# Triage agent decides which language agent should handle the request
triage_agent = Agent(
    model,
    output_type=TriageResult,
    system_prompt=(
        "You are a triage agent. Determine whether the user's request is primarily in Spanish or English. "
        "Return language (either 'spanish' or 'english') and reason (a brief explanation of your choice) "
        "Only choose 'spanish' if the request is entirely in Spanish; otherwise choose 'english'."
    ),
)


async def main():
    user_input = "Hola, ¿cómo estás? ¿Puedes darme el clima para San Francisco CA?"
    triage = await triage_agent.run(user_input)
    triage_output = triage.output
    print("Triage output:", triage_output)
    if triage_output.language == "spanish":
        weather_result = await spanish_weather_agent.run(user_input)
    else:
        weather_result = await english_weather_agent.run(user_input)
    print(weather_result.output)


if __name__ == "__main__":
    asyncio.run(main())

You can replicate with the endpoint that I shared with @DouweM last week, and the model "openai/gpt-oss-20b".

Example Code

Python, Pydantic AI & LLM client version

pydantic-ai==1.6.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions