Route e capacità dei modelli

“Questo modello supporta le chiamate a tool?” sembra una domanda sul modello. Non lo è. È una domanda sul modello e sull'endpoint su cui lo si chiama — e lo stesso modello può rispondere sì su uno e no sull'altro. Questa pagina spiega perché, e come Entity Enricher risolve la questione misurandola invece di fidarsi di un catalogo.

Un modello che supporta una funzionalità e la rifiuta

Se si invia alla famiglia gpt-6 di OpenAI una richiesta con function tool sul classico endpoint /v1/chat/completions, la richiesta viene rifiutata senza appello:

400 Bad Request
Function tools with reasoning_effort are not supported.
Use /v1/responses or set reasoning_effort to 'none'.

Inviando lo stesso modello, gli stessi tool e lo stesso prompt a /v1/responses, la risposta arriva normalmente — su entrambi i canali di output strutturato, con o senza un reasoning effort. Nel modello non è cambiato nulla. È cambiato solo l'indirizzo.

La conseguenza

Una capacità non è una proprietà del solo modello. È una proprietà di una coppia (modello, endpoint). Ogni catalogo che memorizza un singolo vero/falso per modello risponde quindi a una domanda che in realtà non può vedere.

Che cos'è una route

Una route è semplicemente l'endpoint a cui viene inviata una richiesta. Stesso provider, stesso modello, stessa chiave API — ma un formato di trasmissione diverso, una struttura della richiesta diversa e un diverso insieme di regole su ciò che può essere combinato. OpenAI ne offre due, e gran parte del settore ha copiato la più vecchia.

RouteStruttura dello scambioChi la parla
Chat Completions
/v1/chat/completions
2023
Stateless: si invia l'intero elenco di messaggi e si riceve in risposta il messaggio successivo. Tra una chiamata e l'altra non viene conservato nulla sul server.OpenAI e lo standard di fatto del settore copiato da quasi tutti gli altri — xAI, DeepSeek, Alibaba, Groq, Together, Ollama e la maggior parte dei gateway compatibili con OpenAI.
Responses API
/v1/responses
2025
Restituisce un elenco di elementi tipizzati — un elemento di ragionamento, un messaggio, una chiamata a function tool, una chiamata a hosted tool — mantiene lo stato lato server e può trasportare il ragionamento da un turno al successivo.Solo OpenAI. Un endpoint simile che parla il formato Chat Completions non serve automaticamente anche questo.

Ecco perché oggi “la OpenAI API” è un'espressione ambigua: ce ne sono due, si sovrappongono e non applicano le stesse regole.

Perché esistono due API

I modelli di reasoning hanno mandato in crisi il modello a messaggi. Il ragionamento interno di un modello non è un messaggio: non è qualcosa che il modello ha detto all'utente, né qualcosa che l'utente ha detto al modello. Chat Completions dispone solo di un elenco di messaggi, quindi non ha alcuno spazio in cui collocare il ragionamento — e ciò che non riesce a rappresentare lo perde da un turno all'altro.

La Responses API è stata progettata attorno a questa lacuna. Il reasoning è un elemento di prima classe nell'elenco restituito; può essere restituito cifrato e riprodotto al turno successivo, così il modello prosegue dal proprio ragionamento invece di ricostruirlo.

Ciò spiega il rifiuto illustrato sopra

Una chiamata a function tool è un percorso di andata e ritorno: il modello richiede un tool, il codice risponde, il modello prosegue. Su Chat Completions non esiste alcun posto in cui conservare il ragionamento durante quel percorso, quindi la prosecuzione riprenderebbe silenziosamente senza di esso — il modello dovrebbe rifare il ragionamento già pagato, e probabilmente lo rifarebbe in modo diverso.

Il provider rifiuta quindi la combinazione anziché degradare silenziosamente. Il messaggio di errore non indica un limite del modello: è la vecchia API che ammette di non avere uno spazio per ciò che questo modello produce.

Le capacità puntano in direzioni diverse

Se tutte le capacità preferissero lo stesso endpoint, la route sarebbe un dettaglio implementativo a cui nessuno dovrebbe pensare. Ma non è così.

Gli strumenti e la ricerca web richiedono la Responses API

L'output strutturato attraverso il canale tool è esattamente la combinazione che Chat Completions rifiuta su un modello di reasoning, e il tool di ricerca web ospitato dal provider è accettato solo lì.

L'audio binario funziona solo su Chat Completions

Allegare byte audio grezzi non è qualcosa che il percorso della Responses API possa trasportare, quindi un modello con capacità audio è raggiungibile solo attraverso l'endpoint più vecchio.

Un modello, due capacità, due endpoint differenti. Non esiste un unico true/false che sia onesto per entrambe: per questo Entity Enricher registra una mappa delle capacità per route ed è per questo che un'esecuzione che richiede due capacità residenti su due route diverse viene rifiutata in modo esplicito, anziché perderne silenziosamente una.

Come Entity Enricher misura una route

La probe delle capacità non invia una richiesta sintetica scritta a mano. Percorre il vero percorso dell'agente — lo stesso codice seguito da un'esecuzione di arricchimento — con la capacità sotto test forzata attiva, e lascia decidere la risposta del provider. Ciò che viene misurato è quindi ciò che l'applicazione può realmente fare, non ciò che l'API potrebbe teoricamente accettare.

L'intera scala — canali di structured output, visione, PDF, audio, ricerca web, reasoning e il relativo controllo dello sforzo per richiesta — viene eseguita una volta per ogni route che il router può scegliere. Per quasi tutti i provider si tratta di un'unica route, e il test costa esattamente quanto è sempre costato; solo i provider in stile OpenAI, realmente raggiungibili in due modi, vengono misurati due volte.

Una route che non risponde alla sua prima chiamata in testo semplice semplicemente non viene misurata, e un modello verificato viene poi indirizzato solo alle route che hanno risposto — non esiste alcun fallback verso un altro endpoint, né al momento della selezione né quando un'esecuzione fallisce. Un modello per cui nessuna route risponde viene ritirato, e lo stesso vale per un modello le cui route non offrono nessuno dei due canali di output strutturato: il testo non è mai un fallback, quindi un modello così non potrebbe servire nemmeno un arricchimento. Solo una verifica successiva che dimostri la presenza di un canale lo reintegra. Le capacità non vengono mai modificate perché un'esecuzione è fallita: la verifica è l'unica cosa che le misura.

Sì

La richiesta è stata accettata e il modello ha prodotto il tipo di risposta atteso.

Registrato come true misurato per quella route — e prevale su qualsiasi dichiarazione ottenuta tramite scraping.

No

Il provider ha rifiutato esplicitamente la capacità, oppure il client si è rifiutato del tutto di costruire la richiesta.

L'unico esito autorizzato a scrivere un false. Anche un rifiuto è gratuito: non viene mai addebitato.

Sconosciuto

Qualsiasi altra cosa: un rate limit, un livello di accesso mancante, un timeout, un 5xx del provider, un errore non riconosciuto.

Non viene scritto nulla e la probe successiva potrà chiarirlo.

Perché il valore predefinito è “unknown” e mai “no”

I due errori non hanno lo stesso costo. Un unknown errato costa un nuovo test: la capacità viene semplicemente misurata di nuovo in seguito. Un no errato è silenzioso e permanente — declassa il modello ovunque, rimuovendolo dai selettori e dalla decisione di routing, e nessuno scopre mai il perché. Perciò un errore non riconosciuto non dimostra nulla e viene registrato come tale.

Accettato non significa compreso

Un HTTP 200 dimostra che la richiesta è stata accettata. Non dimostra che il modello abbia effettivamente letto l'allegato — un provider può accettare senza problemi un'immagine e passarla a un modello che non la guarda mai. Perciò ogni verifica che trasporta un payload ne trasporta uno la cui risposta può essere controllata:

FunzionalitàPayload inviatoDomanda posta
VisioneUn'immagine rossa uniforme“Quale colore predomina?”
Input PDFUn PDF che contiene esattamente una parola“Quale parola è presente nel documento?”
Input audioUn file audio con un numero contabile di toni“Quanti bip distinti?”

Due risultati distinti, deliberatamente

La risposta di contenuto viene registrata accanto al verdetto e non modifica mai il flag di capacità. Un modello di piccole dimensioni che interpreta male un quadrato rosso supporta comunque la visione: il trasporto ha funzionato, la modalità è stata veicolata, il modello era semplicemente poco efficace. Confondere “non può” con “ha risposto male” cancellerebbe silenziosamente una capacità funzionante per via di una sola parola errata; tenerle distinte permette di conoscere entrambe le cose contemporaneamente.

Affermazioni contro misurazioni

I cataloghi pubblici di modelli come LiteLLM o PricePerToken dichiarano le capacità come un dato assoluto sul modello, senza alcun endpoint associato. Non si tratta di trascuratezza: non esiste un campo per indicarlo. Ma significa che una dichiarazione può essere perfettamente corretta in generale e comunque errata per l'endpoint utilizzato dalla propria esecuzione.

Un'affermazione ricavata via scraping

“Questo modello supporta le chiamate a tool.” Vero da qualche parte. Muto su dove. Utile come punto di partenza per un modello che nessuno ha ancora verificato.

Una misurazione

“Su questo endpoint, questo modello ha accettato chiamate a tool in questo momento.” Indica la route a cui si riferisce, così da poterla confrontare con la route che un'esecuzione seguirà realmente.

Indicare la route è anche ciò che mantiene onesta una misurazione nel tempo. Un verdetto ottenuto su un endpoint che il modello non utilizza più non è una prova migliore di una dichiarazione: è una prova che riguarda altro. Senza la route registrata accanto, una vecchia misurazione sarebbe indistinguibile da una attuale e prevarrebbe sul catalogo per l'endpoint sbagliato. Con la route registrata, semplicemente non si applica e la dichiarazione resta valida finché una misurazione sull'endpoint corretto non la sostituisce.

Come leggerlo nel prodotto

Sia il catalogo dei modelli all'interno dell'app sia il catalogo dei modelli pubblico presentano un selettore Route accanto ai filtri. Cambia la route per cui rispondono le icone di capacità di ogni riga.

Route servita (impostazione predefinita)

Ogni riga si riferisce all'endpoint su cui il modello viene effettivamente servito. È la vista che corrisponde a ciò che si ottiene eseguendo un arricchimento ed è quella da consultare, a meno che non si stia analizzando un endpoint specifico.

Una route dichiarata

Fissando l'intera tabella su un solo endpoint, le icone si riferiscono esclusivamente a quell'endpoint: è così che si vede una capacità comparire o sparire passando dall'uno all'altro ed è così che si confrontano due modelli a parità di condizioni.

Un modello con una sola route raggiungibile non mostra alcun selettore: non c'è nulla da scegliere, e le sue icone rispondono già per l'unico endpoint disponibile. Il selettore appare esattamente quando l'ambiguità è reale.

Che cosa significa per lei

Nulla, nella maggior parte dei casi — ed è proprio questo il punto. Non si sceglie mai una route. Si sceglie un modello e si descrive la propria esecuzione, e il router seleziona l'endpoint in grado di supportare ciò che l'esecuzione richiede: i tool e la ricerca web vanno dove sono accettati, un allegato audio va dove l'audio è supportato.

L'unico caso che noterà è un conflitto reale: ad esempio, richiedere la ricerca web e allegare un file audio allo stesso modello OpenAI, poiché nessun singolo endpoint supporta entrambe le cose. Quell'esecuzione viene rifiutata esplicitamente, indicando le due capacità e ciò che ciascuna route può trasportare, anziché essere avviata scartando silenziosamente una delle due. È sufficiente eliminare un requisito, oppure scegliere un modello che supporti entrambi, e l'esecuzione procede.

E quando un'icona di capacità sorprende, il selettore Route è la spiegazione: quasi sempre si tratta di un modello la cui risposta dipende da dove è stata posta la domanda.