> ## Documentation Index
> Fetch the complete documentation index at: https://docs.weflayr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-heal

> The gateway adapts each request to the model it is sent to, instead of letting the provider refuse it with a 400.

Every model takes a different set of parameters. A `temperature` that GPT-5.4 takes without reasoning is refused once it reasons, Claude Opus 4.7 and later refuse a `top_p`, Anthropic has no `seed`, some models cannot turn thinking off. The same request that works on one model fails with a 400 on another.

That matters most when calls are routed: a routing strategy or a [fallback](https://docs.weflayr.com/concepts/fallback-and-model-health.md) can send your request to a model your code was never written for. Self-heal adapts the request to that model, so the call is answered instead of failing.

Whether self-heal is on or off, the gateway always writes your request in each provider's own format (reasoning settings, cache breakpoints...). Self-heal goes one step further: it removes or adjusts the parameters a model does not take, which can slightly change how the model answers. It does this before the request is sent: the provider never sees the parameter it would refuse, so there is no failed call, no retry and no extra round trip to the provider.

## What self-heal does

### Thinking

| Your request has | Sent to | The gateway |
| - | - | - |
| any thinking setting, including turning thinking off | a model that does not think | removes it |
| a thinking level or token budget | a model that thinks at a depth of its own | removes it |
| a request to turn thinking off | a model that always thinks and can think between tool calls only | replaces it with thinking between tool calls only, so the model does not think before answering |
| a request to turn thinking off | another model that always thinks | replaces it with the lowest thinking level the model takes, or removes it when the model takes no level |
| a thinking level the model does not offer, including a token budget (read as the closest level) and thinking turned on with no level (read as `medium`) | a model that takes some levels | replaces it with the closest level it takes, the higher one when two are as close |
| `reasoning.summary` | a model that does not think, or that thinks only when asked and the request does not ask | removes it |

### Sampling and output parameters

| Your request has | Sent to | The gateway |
| - | - | - |
| `temperature` | a model that does not take it while it thinks, or while it does not think | removes it |
| `top_p` | a model that does not take it while it thinks, or while it does not think | removes it |
| `top_p` together with `temperature` | a model that takes one or the other, not both | removes `top_p` |
| `top_k` | a model that does not take it while it thinks, or while it does not think | removes it |
| `top_k` | a model that never takes it | removes it |
| `logprobs` (and `top_logprobs`) | a model that does not take them while it thinks, or while it does not think | removes them |
| `logprobs` (and `top_logprobs`) | a model that never takes them | removes them |
| `n` above 1 | a model that answers one choice only while it thinks, or while it does not think | removes it |
| `n` above 1 | a model that always answers one choice only | removes it |
| `stop` | a model that does not take stop sequences | removes it |
| a stop sequence made only of whitespace | a model that refuses it | removes it, and `stop` when none is left |
| more stop sequences than the model takes | a model with a maximum | keeps the first ones it takes |
| `max_output_tokens` (or `max_completion_tokens`, `max_tokens`) below the fewest output tokens the model takes | a model with a minimum | raises it to that minimum |
| `presence_penalty`, `frequency_penalty`, `seed` | a model that does not take them | removes them |

### Tools

| Your request has | Sent to | The gateway |
| - | - | - |
| a forced `tool_choice` (`required` or naming a function) | a model that chooses by itself whether to call a tool, in the region called | replaces it with `auto` |
| `parallel_tool_calls: false` | a model that cannot turn parallel tool calls off | removes it |

### Prompt caching

| Your request has | Sent to | The gateway |
| - | - | - |
| cache breakpoints (on messages, tools, the web search or in `provider_options`) | a model whose cache breakpoints write no cache | removes them all |
| a cache breakpoint `ttl` the provider does not offer | a model that offers other cache lifetimes | replaces it with the closest one offered, the longer one when two are as close |
| a cache breakpoint `ttl` | a model that caches for a fixed lifetime and takes no `ttl` | removes the `ttl` |
| a cache breakpoint on a message whose role the model refuses breakpoints on (an `assistant` message on Kimi K3 on Bedrock) | that model | removes it |
| more cache breakpoints than the provider takes, where it would refuse the request or ignore every breakpoint | that model | keeps the last ones it takes |
| `prompt_cache_retention`, `prompt_cache_options` | a model that does not take them | removes them |

## What self-heal does not do

Self-heal only makes small changes, the kind that keep your app working with at most a slight difference in the answer, such as dropping a `seed` or moving a thinking level one step. It never makes a change with a big effect, such as a different price per token or a question asked without its image:

* **Service tier:** a `service_tier` no provider of the model offers is not removed by self-heal, since it changes the price of the call: it is removed only when your request lists it in [`drop_inputs_if_unsupported`](https://docs.weflayr.com/api/gateway/responses#param-drop-inputs-if-unsupported), and refused with a 400 otherwise.
* **Inputs the answer depends on:** an image, a PDF, tools, a response schema or a web search sent to a model that does not take them is refused with a 400, since removing it would change the question asked.
* **Forced web search:** a `tool_choice` forcing the web search, on a model that chooses by itself whether to call a tool, is refused with a 400 rather than replaced with `auto`, since the model could then answer without searching.

## Configuration

Set it per call with the [`self_heal` field](https://docs.weflayr.com/api/gateway/responses#param-self-heal).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.