“Este modelo suporta chamadas de ferramentas?” parece uma pergunta sobre o modelo. Não é. É uma pergunta sobre o modelo e o endpoint onde o invoca — e o mesmo modelo pode responder que sim num e que não noutro. Esta página explica porquê e como o Entity Enricher resolve a questão medindo-a em vez de acreditar num catálogo.
Envie à família gpt-6 da OpenAI um pedido com ferramentas de função no endpoint clássico /v1/chat/completions e o pedido é rejeitado de imediato:
400 Bad Request Function tools with reasoning_effort are not supported. Use /v1/responses or set reasoning_effort to 'none'.
Envie o mesmo modelo, as mesmas ferramentas e o mesmo prompt para /v1/responses e ele responde normalmente — em ambos os canais de saída estruturada, com ou sem esforço de raciocínio. Nada mudou no modelo. Mudou apenas o endereço.
A consequência
Uma capacidade não é uma propriedade apenas do modelo. É uma propriedade do par (modelo, endpoint). Por isso, qualquer catálogo que guarde um único verdadeiro/falso por modelo está a responder a uma pergunta que, na verdade, não consegue ver.
Uma rota é simplesmente o endpoint para onde um pedido é enviado. O mesmo fornecedor, o mesmo modelo, a mesma chave de API — mas um formato de transmissão diferente, uma estrutura de pedido diferente e um conjunto de regras diferente sobre o que pode ser combinado. A OpenAI disponibiliza duas e a maior parte da indústria copiou a mais antiga.
| Rota | Formato da troca | Quem a fala |
|---|---|---|
Chat Completions /v1/chat/completions2023 | Sem estado: envia a lista completa de mensagens e recebe de volta a mensagem seguinte. Nada é guardado no servidor entre chamadas. | A OpenAI e o padrão de facto da indústria copiado por quase todos os outros — xAI, DeepSeek, Alibaba, Groq, Together, Ollama e a maioria dos gateways compatíveis com OpenAI. |
API Responses /v1/responses2025 | Devolve uma lista de itens tipados — um item de raciocínio, uma mensagem, uma chamada a uma ferramenta de função, uma chamada a uma ferramenta alojada —, mantém o estado no servidor e pode transportar o raciocínio de um turno para o seguinte. | Apenas OpenAI. Um endpoint semelhante que fale o formato Chat Completions não serve automaticamente este. |
É por isto que “a API OpenAI” é hoje ambígua: existem duas, sobrepõem-se e não aplicam as mesmas regras.
Os modelos de raciocínio quebraram o modelo de mensagens. O raciocínio interno de um modelo não é uma mensagem: não é algo que ele lhe tenha dito, nem algo que você lhe tenha dito. O Chat Completions tem apenas uma lista de mensagens, pelo que não tem onde colocar o raciocínio — e aquilo que não consegue representar, descarta-o entre turnos.
A Responses API foi concebida em torno dessa lacuna. O raciocínio é um item de primeira classe na lista devolvida; pode voltar encriptado e ser reproduzido na interação seguinte, para que o modelo continue a partir do seu próprio raciocínio em vez de o reconstruir.
Uma chamada de ferramenta de função é uma ida e volta: o modelo pede uma ferramenta, o seu código responde, o modelo continua. Na Chat Completions não há onde guardar o raciocínio ao longo dessa ida e volta, pelo que a continuação seria retomada silenciosamente sem ele — o modelo teria de refazer o raciocínio que já pagou e provavelmente refá-lo-ia de forma diferente.
Por isso, o fornecedor recusa a combinação em vez de degradar silenciosamente. A mensagem de erro não é uma limitação do modelo; é a API mais antiga a admitir que não tem espaço para aquilo que este modelo produz.
Se todas as capacidades preferissem o mesmo endpoint, a rota seria um detalhe de implementação em que ninguém teria de pensar. Mas não preferem.
A saída estruturada através do canal da ferramenta é exatamente a combinação que o Chat Completions recusa num modelo de raciocínio, e a ferramenta de pesquisa web alojada pelo fornecedor só é aceite aí.
Anexar bytes de áudio em bruto não é algo que o caminho da Responses API consiga transportar, pelo que um modelo com capacidade de áudio só é acessível através do endpoint mais antigo.
Um modelo, duas capacidades, dois endpoints diferentes. Não existe um único verdadeiro/falso que seja honesto quanto a ambos — é por isso que o Entity Enricher regista um mapa de capacidades por rota e que uma execução que necessite de duas capacidades situadas em duas rotas diferentes é recusada explicitamente, em vez de perder uma delas em silêncio.
A sondagem de capacidades não envia um pedido sintético escrito à mão. Percorre o verdadeiro caminho do agente — o mesmo código que uma execução de enriquecimento utiliza — com a capacidade em teste forçada, e deixa que a resposta do fornecedor decida. O que é medido é, por isso, aquilo que a aplicação consegue realmente fazer, e não aquilo que a API poderia teoricamente aceitar.
Toda a escada — canais de saída estruturada, visão, PDF, áudio, pesquisa web, raciocínio e o respetivo controlo de esforço por pedido — corre uma vez por cada rota que o router pode escolher. Para quase todos os fornecedores isso é uma única rota, e a sondagem custa exatamente o que sempre custou; só os fornecedores com formato OpenAI, que podem mesmo ser alcançados por duas vias, são medidos duas vezes.
Uma rota que não responde à sua primeira chamada em texto simples simplesmente não é medida, e um modelo sondado é depois encaminhado apenas para as rotas que responderam — não há recurso a outro endpoint, nem no momento da seleção nem quando uma execução falha. Um modelo para o qual nenhuma rota responde é retirado, tal como aquele cujas rotas não disponibilizam nenhum dos canais de saída estruturada: o texto nunca é uma alternativa de recurso, pelo que um modelo assim não conseguiria servir um único enriquecimento. Só uma sondagem posterior que comprove um canal o reativa. As capacidades nunca são alteradas por uma execução ter falhado — a sondagem é a única coisa que as mede.
O pedido foi aceite e o modelo produziu o tipo de resposta esperado.
Registado como um verdadeiro medido para essa rota — e prevalece sobre qualquer afirmação obtida por scraping.
O fornecedor rejeitou explicitamente a capacidade, ou o cliente recusou-se mesmo a construir o pedido.
O único resultado autorizado a escrever um false. Uma rejeição também é gratuita: nunca é faturada.
Qualquer outra coisa: um limite de taxa, um nível de acesso em falta, um tempo limite excedido, um 5xx do fornecedor, um erro não reconhecido.
Nada é registado e a próxima sondagem poderá resolver a questão.
Os dois erros não custam o mesmo. Um unknown errado custa uma nova sondagem: a capacidade é simplesmente medida outra vez mais tarde. Um no errado é silencioso e permanente — despromove o modelo em todo o lado, retirando-o dos seletores e da decisão de encaminhamento, e ninguém chega a descobrir porquê. Por isso, uma falha não reconhecida não prova nada e é registada como não provando nada.
Um HTTP 200 prova que o pedido foi aceite. Não prova que o modelo leu de facto o anexo — um fornecedor pode perfeitamente aceitar uma imagem e entregá-la a um modelo que nunca lhe presta atenção. Por isso, todas as sondagens que transportam um payload transportam um cuja resposta pode ser verificada:
| Capacidade | Payload enviado | Pergunta feita |
|---|---|---|
| Visão | Uma imagem vermelha uniforme | “Que cor domina?” |
| Entrada de PDF | Um PDF que contém exatamente uma palavra | “Que palavra está no documento?” |
| Entrada de áudio | Um ficheiro de áudio com um número contável de tons | “Quantos sinais sonoros distintos?” |
Dois resultados separados, deliberadamente
A resposta de conteúdo é registada ao lado do veredicto e nunca inverte o indicador de capacidade. Um modelo pequeno que interprete mal um quadrado vermelho continua a suportar visão — o transporte funcionou, a modalidade foi transportada, o modelo era simplesmente fraco. Confundir «não consegue» com «correu mal» eliminaria silenciosamente uma capacidade funcional por causa de uma palavra errada; mantê-las separadas informa-o das duas coisas ao mesmo tempo.
Os catálogos públicos de modelos, como o LiteLLM ou o PricePerToken, declaram as capacidades como um facto simples sobre o modelo, sem qualquer endpoint associado. Não é desleixo — não existe campo para isso. Mas significa que uma afirmação pode estar perfeitamente correta em geral e, ainda assim, errada para o endpoint que a sua execução utiliza.
“Este modelo suporta chamadas de ferramentas.” Verdade nalgum sítio. Sem dizer onde. Útil como ponto de partida para um modelo que ainda ninguém sondou.
“Neste endpoint, este modelo aceitou chamadas de ferramentas neste momento.” Identifica a sua rota, pelo que pode ser comparada com a rota que uma execução irá realmente seguir.
Identificar a rota é também o que mantém uma medição honesta ao longo do tempo. Um veredicto obtido num endpoint que o modelo já não utiliza não é uma prova melhor do que uma afirmação — é prova sobre outra coisa. Sem a rota registada ao seu lado, uma medição antiga seria indistinguível de uma atual e prevaleceria sobre o catálogo no endpoint errado. Com a rota registada, simplesmente não se aplica, e a afirmação mantém-se até que uma medição no endpoint correto a substitua.
Tanto o catálogo de modelos dentro da aplicação como o catálogo de modelos público têm um seletor Rota junto aos filtros. Altera a rota pela qual os ícones de capacidade de cada linha estão a responder.
Cada linha responde pelo endpoint em que esse modelo é efetivamente servido. É esta a vista que corresponde ao que obtém quando executa um enriquecimento e é a que deve consultar, salvo se estiver a investigar um endpoint específico.
Fixe toda a tabela num único endpoint e os ícones passam a responder apenas por esse endpoint — é assim que vê uma capacidade aparecer ou desaparecer à medida que alterna entre eles e que compara dois modelos em igualdade de circunstâncias.
Um modelo com apenas uma rota acessível não mostra qualquer seletor: não há nada a escolher e os seus ícones já respondem pelo único endpoint que tem. O seletor aparece exatamente quando a ambiguidade é real.
Nada, na maior parte das vezes — e é esse o objetivo. Nunca escolhe uma rota. Escolhe um modelo e descreve a sua execução, e o router escolhe o endpoint capaz de suportar aquilo de que a execução precisa: as ferramentas e a pesquisa web vão para onde são aceites, um anexo de áudio vai para onde o áudio é suportado.
O único caso que irá notar é um conflito genuíno — pedir pesquisa web e anexar um ficheiro de áudio ao mesmo modelo OpenAI, por exemplo, já que nenhum endpoint serve os dois. Essa execução é recusada explicitamente, indicando as duas capacidades e o que cada rota consegue transportar, em vez de ser executada descartando uma delas em silêncio. Elimine um dos requisitos, ou escolha um modelo que sirva ambos, e a execução prossegue.
E quando um ícone de capacidade o surpreende, o seletor de Rota é a explicação: está quase sempre perante um modelo cuja resposta depende de onde a pergunta foi feita.