OpenRouter devolve respostas diferentes para o mesmo modelo? Como fixar o provedor com provider.only

Fixar provedor no OpenRouter resolve aquele problema da mesma chamada responder de jeitos diferentes: o roteamento automático distribui o mesmo model ID entre backends distintos, e cada provedor roda software de serving e configuração próprios. O fluxo é curto: chame GET https://openrouter.ai/api/v1/models/{author}/{slug}/endpoints pra listar os provedores com pricing, supported_parameters, status e estatísticas recentes, copie o slug exato na página do modelo e mande {"provider": {"only": ["deepinfra"]}} no corpo. Com allow_fallbacks: false a rota não escapa, e o campo provider da resposta mostra quem atendeu 🙂
Fala aí, beleza? A mesma chamada de API, o mesmo model ID, o mesmo prompt, e o comportamento muda de uma execução pra outra
Não é azar e nem é o seu prompt: o OpenRouter roteia a mesma requisição para provedores de inferência diferentes, e cada um roda software de serving, otimizações e configurações próprias
Em 11/09/2026 o Simon Willison linkou no blog dele o post So you want to use OpenRouter?, do Mohamed Moustafa, e destacou dois efeitos bem chatos disso: alguns provedores não têm capacidade de visão em modelos de visão, e a opção de esforço de raciocínio é processada de formas diferentes
A boa notícia é que dá pra travar a rota, e é isso que a gente vai fazer aqui passo a passo
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 116 aulas
- 4 projetos
- 9h 23min
Por que o mesmo modelo responde diferente a cada execução
O ponto de venda do roteamento automático é justamente ele escolher o backend disponível pra você
O efeito colateral é que um único model ID pode ser atendido por vários provedores distintos, e o que muda entre eles não é o peso do modelo, é a infraestrutura em volta
"Infraestrutura em volta" quer dizer o quê? Software de serving, otimizações e configurações de cada provedor
Duas diferenças observáveis apareceram na discussão levantada por Moustafa e comentada por Willison:
- provedores que não entregam visão mesmo o modelo sendo de visão
- tratamento diferente do esforço de raciocínio de um provedor pro outro
Vale separar bem as coisas aqui, porque é fácil confundir esse cenário com modelos diferentes dando respostas diferentes, que é outro problema
Aqui o modelo é o MESMO, quem muda é o backend que atende a sua requisição
E olha, as opiniões sobre o que fazer com isso são do Moustafa, não minhas: ele escreveu, o Willison linkou, eu tô te mostrando o mecanismo oficial pra resolver
O que você precisa antes de começar
Pouca coisa, nada de PC da Nasa aqui:
- conta no OpenRouter
- chave de API
- o model ID no formato
{author}/{slug} - um cliente HTTP (curl ou equivalente)
Tome cuidado com isso: as restrições de provedor da sua conta funcionam como TETO
A lista only da requisição só estreita dentro desse teto, ela nunca amplia
Se a interseção entre os dois der vazio, a requisição falha com 404, e não adianta xingar o código
Passo a passo: listar os provedores e travar a rota com provider.only
1. Liste os provedores do modelo com /endpoints
O endpoint oficial que devolve a lista de provedores disponíveis de um modelo é esse:
curl https://openrouter.ai/api/v1/models/{author}/{slug}/endpoints
Os parâmetros author e slug são obrigatórios
A resposta traz os metadados do modelo mais um array de endpoints, e cada endpoint vem com pricing, supported_parameters, status e estatísticas recentes de desempenho
O erro comum deste passo: mandar só o slug e esquecer o author, ou seja, montar a URL com metade do model ID
2. Escolha o provedor olhando capacidade, não só preço
Antes de escolher, lê o supported_parameters de cada endpoint
É ali que você vê se aquele backend declara reasoning, tools, structured_outputs e companhia
O catálogo do OpenRouter usa esse mesmo campo pra cobrir parâmetros de sampling (temperature, top_p, top_k, min_p, top_a, frequency_penalty, presence_penalty, repetition_penalty, stop, seed, max_tokens, logit_bias, logprobs, top_logprobs) e features (tools, json_mode, structured_outputs, logprobs, web_search, reasoning)
E tem mais: TTFT, throughput e uptime ficam expostos publicamente na página de cada modelo, então dá pra comparar sem precisar instrumentar nada
O erro comum deste passo: fechar no mais barato e só depois descobrir que o parâmetro que o seu app depende nem aparece na lista daquele endpoint
3. Copie o slug exato do provedor
Nas páginas de modelo do OpenRouter tem um botão de cópia do lado do nome do provedor
Usa ele, sério
O detalhe que pega muita gente é a diferença entre slug base e slug completo:
deepinfracasa TODOS os endpoints daquele provedor, incluindo regiões e variantesdeepinfra/turbotrava só aquela variante
O erro comum deste passo: usar o slug base achando que travou tudo, e continuar pulando entre variantes do mesmo provedor
4. Mande provider.only no corpo da requisição
provider.only é uma allow-list de slugs enviada no corpo da requisição
Com ela, nenhum outro provedor de inferência é usado:
{
"provider": {
"only": ["deepinfra", "nebius"]
}
}
Se você conhece allow-list de firewall, é a mesma ideia: o que não está na lista não entra
O erro comum deste passo: esperar que o only passe por cima das preferências da conta
Ele não passa, e quando nenhum provedor satisfaz o teto da conta E a lista only ao mesmo tempo, você leva o 404
5. Feche a rota com allow_fallbacks: false
O campo provider.allow_fallbacks controla provedores de backup para o mesmo modelo, e o padrão dele é true
Ou seja: sem mexer nisso, você não travou de verdade
{
"provider": {
"only": ["deepinfra"],
"allow_fallbacks": false
}
}
Com false, a requisição FALHA em vez de sair da lista aprovada
O erro comum deste passo: deixar no padrão, ver o comportamento variar de novo e achar que o only não funciona
6. Verifique pelo campo provider da resposta
A resposta da API do OpenRouter inclui um campo provider indicando quem atendeu a requisição, e ele aparece inclusive nos eventos SSE de streaming
Esse é o seu resultado verificável: repete a mesma chamada algumas vezes e confere se o valor se mantém
{"provider":"openai"}
O erro comum deste passo: rodar uma vez só
Uma execução não prova estabilidade, prova sorte 😀
Outros filtros do objeto provider: order, ignore, sort, quantizations e max_price
O only é o mais bruto, mas não é o único
O objeto provider aceita um conjunto de campos, e cada um resolve um problema diferente:
| Campo | Pra que serve |
|---|---|
only |
allow-list de slugs: nenhum outro provedor de inferência é usado |
order |
prioriza uma ordem de provedores |
ignore |
exclui provedores da rota |
sort |
ordena por preço, throughput ou latência |
allow_fallbacks |
liga ou desliga provedores de backup (padrão true) |
quantizations |
filtra provedores pela precisão declarada |
max_price |
teto de preço por provedor, em dólares por milhão de tokens |
O quantizations aceita os valores int4, int8, fp4, fp6, fp8, fp16, bf16 e fp32:
{
"provider": {
"quantizations": ["fp8"]
}
}
E o max_price funciona assim:
{
"provider": {
"max_price": { "prompt": 1, "completion": 2 }
}
}
Nesse exemplo a requisição só vai pra provedor com no máximo US$ 1 por milhão de tokens de prompt e US$ 2 por milhão de completion
Uma ressalva importante, e ela é do Moustafa: filtrar por precisão é um proxy ruim de qualidade, e o filtro duro reduz o conjunto de provedores disponíveis pra fallback quando um deles cai
Faz sentido pensar nisso antes de sair fixando fp8 em tudo
Problemas comuns ao fixar o provedor (e como prevenir)
404 na cara. Causa: nenhum provedor satisfaz ao mesmo tempo as preferências da conta e a lista only da requisição, porque as duas se acumulam como interseção
Prevenção: confira as restrições de provedor da conta ANTES de montar o only, lembrando que a conta é teto e a requisição só estreita
A rota escapa mesmo com only. Causa: allow_fallbacks continua no padrão true
Prevenção: setar false explicitamente quando o objetivo for comportamento estável, aceitando que a chamada pode falhar
Parâmetro aceito num provedor e ignorado em outro. Causa: cada endpoint declara o seu próprio supported_parameters
Prevenção: ler o array de endpoints do /endpoints e cruzar com o que a sua aplicação realmente manda
Slug base pegando variante que você não queria. Causa: deepinfra casa todos os endpoints do provedor, deepinfra/turbo trava a variante
Prevenção: copiar o slug pelo botão da página do modelo, incluindo o sufixo quando existir
Disponibilidade caindo depois da trava. Causa: lista estreita demais, sem margem
Aqui vale lembrar como o roteamento do OpenRouter trata uptime:
| Faixa de uptime | Efeito no roteamento |
|---|---|
| 95% ou mais | prioridade normal |
| 80% a 94% | tráfego reduzido |
| abaixo de 80% | usado só como fallback |
Prevenção: olhar a faixa de uptime do endpoint escolhido antes de fechar a rota nele
Estabilidade x resiliência: o que travar o provedor custa
Agora o lado honesto da história
Rota fixa te dá capacidade e comportamento estáveis entre execuções repetidas, que é exatamente o que você quer quando o app depende de visão, de tools ou de um ajuste específico de raciocínio
O preço disso é resiliência: quanto mais estreita a lista, menos backup você tem quando o provedor cai
Não existe fórmula mágica aqui, existe escolha consciente
Duas recomendações do Moustafa que ajudam a decidir: acompanhar os tokens de raciocínio gerados por provedor pra um mesmo ajuste de esforço, e usar o campo sort pra priorizar throughput quando isso importa mais que preço
Se você quiser mapear o terreno antes, dá pra listar todos os provedores da plataforma com GET https://openrouter.ai/api/v1/providers, e a rede também aparece na página pública openrouter.ai/providers
E sim, isso muda o jeito de pensar quando existem vários provedores para o mesmo modelo, porque a decisão deixa de ser "qual modelo" e vira "qual backend"
Conclusão: rota previsível é requisito, não detalhe
O fluxo inteiro cabe em quatro movimentos: chama o /endpoints do model ID, escolhe o endpoint lendo supported_parameters e as métricas públicas, copia o slug exato e manda provider.only no corpo
Depois confere no campo provider da resposta, que também vem nos eventos de streaming
Próximo passo que eu sugiro antes de levar pra produção: roda a mesma chamada algumas vezes COM e SEM a trava, compara o provedor retornado e anota quais supported_parameters cada endpoint declara
Com esse registro na mão, fixar o provedor deixa de ser chute e vira decisão
As referências: o post de link do Simon Willison publicado em 11/09/2026, o texto original do Mohamed Moustafa no blog dele e a documentação de seleção de provedor do OpenRouter, que é de onde saem os campos usados aqui
até o próximo post! 🙂
Perguntas frequentes
Por que o OpenRouter devolve respostas diferentes para o mesmo model ID?
Porque o OpenRouter roteia a mesma requisição entre múltiplos backends do mesmo model ID, e cada provedor de inferência roda software de serving, otimizações e configurações distintas. O modelo é o mesmo, mas a infraestrutura que atende sua chamada muda de execução pra execução.
provider.only garante 100% que só aquele provedor vai responder?
Só se você também mandar allow_fallbacks: false. O padrão do allow_fallbacks é true, então mesmo com only preenchido o OpenRouter ainda pode usar backup fora da lista. Sem essa combinação, você não travou a rota de verdade.
Por que minha requisição com provider.only cai em erro 404?
Porque as restrições de provedor da sua conta funcionam como teto, e a lista only da requisição só estreita dentro desse teto, nunca amplia. Se a interseção entre o que sua conta permite e o que você colocou no only der vazio, a requisição falha com 404.
Qual a diferença entre usar o slug base e o slug completo do provedor no only?
O slug base, como deepinfra, casa com todos os endpoints daquele provedor, incluindo regiões e variantes. Já o slug completo, como deepinfra/turbo, trava só aquela variante específica. Se você quer travar tudo do provedor, use o base; se quer travar uma variante, copie o slug completo direto no botão de cópia da página do modelo.
Como saber se o provedor que atendeu minha chamada realmente ficou fixo?
A resposta da API do OpenRouter traz um campo provider indicando quem atendeu a requisição, inclusive nos eventos SSE de streaming. O jeito de verificar é repetir a mesma chamada algumas vezes e conferir se esse valor se mantém, já que uma execução única não prova estabilidade.
provider.quantizations resolve o problema de qualidade inconsistente entre provedores?
O campo quantizations filtra provedores pela precisão declarada, com valores como int4, int8, fp4, fp6, fp8, fp16, bf16 e fp32. Mas segundo a opinião do autor do post original, Mohamed Moustafa, filtrar por precisão é um proxy ruim de qualidade, e esse filtro duro ainda reduz o conjunto de provedores disponíveis para fallback quando um cai.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
O que significa “ChatGPT network error” e como resolver
O “ChatGPT Network Error” é uma ocorrência frequente na rotina de muitos usuários do ChatGPT. Porém, poucos compreendem seu significado, quando esse erro surge, etc. […]

Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação
Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação A popularidade da automação de processos com o n8n está em alta, principalmente […]

Como usar o Antigravity do Google: guia completo do zero ao primeiro app
Aprenda neste guia prático como usar o Antigravity do Google: descubra a instalação, configuração, criação de projetos com o Agent Manager e o primeiro deploy, […]
