Agent with no model keeps GPT-5 default model settings when the model provider chooses the model #5414
Description
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
ModelProviderchooses 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
mainat 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
ModelProviderwhoseget_model(None)returns a non-GPT-5 model; the live symptom was observed withOpenAIChatCompletionsModelon 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
szupzj18 commentedon Oct 26, 2026
Thanks for the detailed report and root cause analysis. The
get_model_settingsgap you described — where implicit GPT-5 defaults aren't realigned whenmodel_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.