Skip to content

Agent with no model keeps GPT-5 default model settings when the model provider chooses the model #5414

Open

Description

@DABH

Please read this first

  • Have you read the docs? Yes.
  • Have you searched for related issues? Yes; no issue covers implicit model settings when a ModelProvider chooses the model.

Describe the bug

An Agent that names no model gets the implicit default ModelSettings for the SDK's default model (gpt-5.6-luna today): reasoning=Reasoning(effort="none") and verbosity="low". At run time the Runner realigns those implicit settings with the model that is actually used, but only when the model is named on RunConfig.model or Agent.model (run_internal/turn_preparation.py, get_model_settings). When neither names a model and RunConfig.model_provider.get_model(None) picks the model, the GPT-5 defaults stay and are sent to that model.

For a custom ModelProvider that resolves None to a non-GPT-5 model (a gateway default, a fine-tune, an OpenAI-compatible endpoint), the request then carries reasoning_effort and verbosity. Strict Chat Completions endpoints reject it: Fireworks AI answers 400 Extra inputs are not permitted, field: 'verbosity' for accounts/fireworks/models/gpt-oss-120b. The same agent works once the model is named on the RunConfig or the Agent, because Agent.__post_init__ and get_model_settings then drop the GPT-5 defaults.

Debug information

  • Agents SDK version: 0.24.0 (also reproduced on main at 0dc4cf1 and on 0.20.0)
  • Related library versions: openai 2.54.0
  • Python version: 3.14
  • Operating system: macOS
  • Model and model provider: any custom ModelProvider whose get_model(None) returns a non-GPT-5 model; the live symptom was observed with OpenAIChatCompletionsModel on Fireworks AI (gpt-oss-120b)
  • Does the issue reproduce with the latest Agents SDK release? Yes
  • Does the issue occur consistently or intermittently? Consistently
openai.BadRequestError: Error code: 400 - {'error': {'object': 'error', 'type': 'invalid_request_error', 'code': 'invalid_request_error', 'message': "Extra inputs are not permitted, field: 'verbosity'"}}

Repro steps

Offline, with the SDK's own ScriptedModel, so no provider or API key is needed:

import asyncio

from agents import Agent, RunConfig, Runner
from agents.models.interface import Model, ModelProvider
from agents.testing import ScriptedModel
from openai.types.responses import ResponseOutputMessage, ResponseOutputText


class ProviderWithDefault(ModelProvider):
    """Chooses the model when the agent names none, as a gateway or a worker process would."""

    def __init__(self) -> None:
        message = ResponseOutputMessage(
            id="msg", role="assistant", status="completed", type="message",
            content=[ResponseOutputText(text="hi", type="output_text", annotations=[])],
        )
        self.model = ScriptedModel(steps=[[message]])
        self.model.model = "some-other-model"  # the SDK's own models expose the name this way

    def get_model(self, model_name: str | None) -> Model:
        return self.model  # model_name is None: the provider decides


async def main() -> None:
    provider = ProviderWithDefault()
    agent = Agent(name="Assistant", instructions="Reply with one word.")  # no model named
    await Runner.run(agent, "Say hi.", run_config=RunConfig(model_provider=provider))
    settings = provider.model.calls[0].model_settings
    print(settings.reasoning, settings.verbosity)
    # Actual:   Reasoning(effort='none', ...) low   <- gpt-5.6-luna defaults sent to "some-other-model"
    # Expected: None None


asyncio.run(main())

The live version is the same provider returning OpenAIChatCompletionsModel(model="accounts/fireworks/models/gpt-oss-120b", openai_client=AsyncOpenAI(base_url="https://api.fireworks.ai/inference/v1", api_key=...)); the request body then contains "verbosity": "low" and "reasoning_effort": "none" and Fireworks returns the 400 above. Naming the model with RunConfig(model=...) or Agent(model=...) makes both variants pass.

Expected behavior

When the provider chooses the model, the implicit defaults should follow the chosen model the same way they follow a model named on RunConfig or Agent: a non-GPT-5 model gets ModelSettings(), a GPT-5 model gets that model's defaults. Explicit model_settings should keep passing through unchanged, and a provider-returned model that does not report a name can keep today's fallback.

Proposed fix

Since the contribution policy limits pull requests to collaborators, the fix is on a branch instead: main...DABH:openai-agents-python:fix/implicit-model-settings-provider-model

It passes the model resolved by get_model into get_model_settings and, only in the fallback where neither run_config.model nor agent.model names the model, aligns the implicit defaults with the resolved model's model attribute when it is a string (as OpenAIResponsesModel, OpenAIChatCompletionsModel, and LitellmModel expose it). Both call sites in run_loop.py (streamed and non-streamed) pass the model. Tests in tests/test_run_config.py cover the provider-chosen non-GPT-5 and GPT-5 cases, explicit settings, an unnamed model, the existing RunConfig.model and Agent.model precedence, and the streamed path. make format, make lint, make typecheck, and make tests pass on the branch. Happy to turn it into a PR if a collaborator wants to adopt it.

Activity

  1. szupzj18 commented on Oct 26, 2026

    @szupzj18

    Thanks for the detailed report and root cause analysis. The get_model_settings gap you described — where implicit GPT-5 defaults aren't realigned when model_provider.get_model(None) resolves the model — makes sense.

    I noticed you have a fix in temporalio/ai-integrations#178. Do you plan to submit it upstream to openai-agents-python? If so, I'll defer to you. If you'd rather I take it, I'm happy to open a PR with a regression test.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions