What does require_parameters do in an OpenRouter provider block?
answer
- capability filter, not a translator
- the danger is a 200 in the wrong shape
- default leaves you exposed
- narrows the pool you can fail over into
- pair it with response-shape assertions
basics
~20 sSet to true, it restricts routing to upstream providers that support every parameter in your request. It defaults to false, which lets OpenRouter route to a provider that quietly ignores a parameter such as tools or a JSON schema, so you get a valid-looking answer in the wrong shape.
solid answer
~50 sProviders hosting the same model do not all implement the same request surface: some accept tool definitions, structured-output schemas, seeds or log probabilities, others do not. With `provider.require_parameters` at its default `false`, OpenRouter may route your request to an upstream that lacks a feature you sent; that provider drops the unsupported field and answers anyway, so you receive prose where your code expected a tool call or schema-conformant JSON. Setting `require_parameters: true` filters the candidate pool down to providers that support all parameters present in the request, which is what you want for any structured or agentic path. The cost is a smaller pool: fewer candidates means less failover headroom, possibly a pricier or slower upstream, and — if no provider qualifies — a failed request instead of a degraded one. That is usually the right trade, because a silently reshaped response is harder to detect than an error.
code
json · 18 lines{
"model": "vendor-a/model-name",
"provider": { "require_parameters": true },
"tools": [
{
"type": "function",
"function": {
"name": "get_invoice_total",
"parameters": {
"type": "object",
"properties": { "invoice_id": { "type": "string" } },
"required": ["invoice_id"]
}
}
}
],
"messages": [{ "role": "user", "content": "Total for INV-42?" }]
}go deeper
Know that providers hosting the same model do not all support the same request features, and that this flag keeps your request away from ones that do not.
Explain the default (false), that unsupported parameters are dropped rather than rejected, and that turning the flag on filters candidate providers before selection.
Show the production reasoning: which paths need it, that it trades failover headroom and possibly cost for correctness, and that you still assert on response shape and log the serving provider.
Own the standard — which traffic classes must carry the flag, what the reduced pool does to availability budgets, and how shape violations are detected and escalated across services.
## The failure it prevents OpenRouter's whole value proposition is that one request shape reaches many models across many upstream providers. The leak in that abstraction is **capability**: the providers serving a given model differ in which request parameters they actually implement. Tool/function definitions, strict structured output, `seed`, log probabilities, and various sampling controls are all things one upstream may honour and another may not. When the gateway routes to a provider that does not implement a parameter you sent, the parameter is not an error — it is simply not applied. The provider returns a perfectly well-formed chat completion that ignores your instruction. Your service then receives natural-language prose where it expected a `tool_calls` array, or free-form JSON-ish text where it expected a schema-conformant object. The HTTP status is 200. Nothing looks broken until a parser throws downstream, or worse, until a lenient parser accepts garbage. This is the single nastiest class of bug in gateway routing, because it is **non-deterministic**: it appears only on the requests that happened to land on the weaker upstream, which means it appears under load, during a failover, or after a provider mix change you did not make. ## What the flag does `provider.require_parameters` is a boolean, default `false`. Set it to `true` and OpenRouter narrows the candidate providers to those that support **all** parameters present in the request before it picks one. It is a routing filter, evaluated per request against what you actually sent — so a plain chat request keeps a wide pool, while the same code path sending tools gets a narrower one automatically. Crucially it is a filter, not a polyfill. It cannot make a provider support tool calling; it can only refuse to send tool-calling traffic to a provider that lacks it. And it operates within the chosen model — it does not rescue you from choosing a *model* that has no tool support at all. If your model fallback list crosses to a model whose family does not do structured output, `require_parameters` will not save the request, because the limitation is in the model, not the upstream. ## The cost of turning it on Every filter shrinks the pool, and a shrunken pool is a resilience cost. Consequences worth stating out loud in an interview: - **Less failover headroom.** If only two upstreams qualify, an outage at both is now a hard failure that the unfiltered pool might have absorbed. - **Possible price and latency change.** The qualifying providers may not be the cheapest or the fastest, so a filter you added for correctness moves your cost and p95. - **Hard failure when nothing qualifies.** You get an error saying no provider meets the routing requirements. That is louder — and far better — than a wrong-shaped 200, but it is a new failure mode your callers must handle. ## How to decide Split traffic by whether shape matters. Extraction pipelines, agentic tool loops, function-calling paths and anything whose output feeds a parser should send `require_parameters: true` and treat the resulting error as a real incident. Conversational or summarisation traffic, where any coherent text is acceptable, does not need it and benefits from the wider pool. Combine it with the other provider fields rather than treating it as a substitute: `order` or `only` still express preference and compliance, `allow_fallbacks` still decides whether exhaustion is fatal, and `require_parameters` layers a capability predicate on top of whatever pool those leave you. ## Verifying it in practice Do not trust configuration alone. Assert on the response: if you asked for a tool call, fail the request when `tool_calls` is absent rather than falling through to text handling; if you asked for schema output, validate against the schema every time. Log the serving provider alongside those validation failures — when a shape error correlates with one upstream, you have found the capability gap the flag exists to close, and you can additionally `ignore` that provider. ## Common mistakes Assuming an unsupported parameter produces an error (it does not — it is dropped); assuming the flag guarantees identical behaviour across qualifying providers (it guarantees support, not quality); assuming it defaults to on; and enabling it globally without noticing that it just halved the failover pool for every request your service makes.
- If require_parameters is false and the chosen provider does not support tools, what does the caller see?A successful response with ordinary assistant text and no tool call. The provider drops the unsupported field rather than rejecting the request, so the status code is 200 and only your parser notices. That is why the safe pattern is to assert on shape — treat a missing tool call on a request that required one as an error — and to log the serving provider so you can correlate failures with a specific upstream.
- Does require_parameters help if your models fallback array crosses to a model without tool support?No. It filters *providers* for the model currently being attempted; it cannot add a capability the model itself lacks. A fallback model that does not do tool calling will either fail or answer in prose regardless of the flag. Model-level capability has to be handled by curating the fallback list — every entry evaluated against the same prompts, tools and parsers as the primary.
- What is the operational downside of enabling it on every request by default?It shrinks the eligible provider pool for all traffic, including requests that never needed the guarantee. Less headroom means an upstream outage is likelier to surface as a hard failure, and the qualifying providers may be pricier or slower, moving both unit cost and tail latency. The better pattern is per-path: on for structured and agentic calls, off for plain conversational traffic.
saying these in an interview costs you the question
- Thinks an unsupported parameter causes an error rather than being ignored
- Assumes require_parameters defaults to true
- Believes it can add tool support to a provider that lacks it
- Thinks it guarantees identical output quality across qualifying providers
- Enables it globally without noticing the shrunken failover pool