Model-specific API parameter errors

I’d like to complain a bit about how the responses API is implemented with respect to parameters. In our system, we’d like to use the same code and make it configurable as to which model we use (gpt-5, gpt-5-min, gpt-4o-mini, etc.) But when we do this, we have found that some of the parameters are model-specific. For example the temperature and reasoningEffort parameters are accepted in some models and not others. I understand why this is the case. However, it is very inconvenient that we get errors back when we include a parameter along with a model that doesn’t support it.

We are using the npm openai library. So we like to depend on the type definitions to tell us what the parameters are and how they can be configured. But these do not take into account the model dependencies. So we flip to a different model and then suddenly, CRASH, the API calls error out telling us about the incompatibility of one of the parameters. It certainly doesn’t feel right that we should be building in all of the same logic into our code about interrelationships between models and parameters.

Why not simply ignore parameters if the model doesn’t support them? You could include a warning in the response if you want to. This would save us a lot of time.

It gets way more preposterous than that.

  • Want to use “prediction” - only on Chat Completions with gpt-4o - and then, with that, max_completion_tokens isn’t supported, only max_tokens (as your excess cost is completely uncontrollable).

  • Want to simply include encrypted reasoning output items in the response? Not if you also store response.id, pal.

  • Want your app to capture any code interpreter code? Don’t use “include” for it unless you actually have the tool placed in that turn, or else server error.


I had an AI convert some Python conditional validation and success-making to javascript to communicate how “simple” it is to add the first layer of “model-specific”…

// ──────────────────────────
// Everything above this line
// has already been defined
// (conversationId, userInput,
//  maxOut, etc.)
// ──────────────────────────

// some stuff you might wish for – but aren't going to get through
const model             = 'o3';
const reasoningEffort   = 'minimal';
const reasoningSummary  = 'auto';          // don't ask why some take only "detailed" or "concise"…

const isIdVerified = false;                // org === false? no reasoning summary, no streaming advanced reasoning, no o3, etc.

/** @type {{[key:string]: any}} */
const payload = {                          // basic template of the Responses-API request
  model,                                   // which model to run
  conversation: conversationId,            // use pre-created server-side history
  input: userInput,                        // latest user message (string or role–dict list)
  max_output_tokens: maxOut,               // reasoning plus output budget
  store: true,                             // store for response.id reuse or conversation API
  stream: true,                            // will be set false if unsupported by ID verification
};

// ──────────────────────────
// ID-verification gatekeeping
// ──────────────────────────
if (!isIdVerified) {
  if (model.startsWith('o3')) {
    throw new Error("Model 'o3' requires ID verification, period.");
  }
  if (model.startsWith('o4-mini') || model.startsWith('gpt-5')) {
    payload.stream = false;
  }
}

// ──────────────────────────
// Reasoning block decisions
// ──────────────────────────
const gpt5Family     = model.startsWith('gpt-5');
const reasoningModel =
  model.startsWith('o') || (gpt5Family && model !== 'gpt-5-chat-latest');

if (reasoningModel) {
  const effort =
    reasoningEffort === 'minimal' && !gpt5Family ? 'low' : reasoningEffort;

  const reasoningBlock = { effort };

  if (isIdVerified) {
    reasoningBlock.summary = reasoningSummary;
  }
  payload.reasoning = reasoningBlock;
} else {
  // fallback defaults when no dedicated reasoning model is used
  payload.temperature = 0.5;
  payload.top_p       = 0.9;
}

// `payload` is now a fully-validated request body and can be passed

Then, good luck if you don’t even know what is in a prompt id…