Créer une couche de compatibilité API Responses dans une passerelle AI API
Une passerelle API Responses n’est pas seulement un proxy de chat complet avec une nouvelle route. Préservez les éléments de réponse, l’état, les appels d’outils, les flux, la continuité du raisonnement, l’attribution d’utilisation et le comportement de rétrogradation avec une couche de compatibilité de premier ordre.
N'implémentez pas /v1/responses en traduisant chaque requête en /v1/chat/completions et en espérant que la forme soit suffisamment proche. Cet adaptateur peut renvoyer du texte, mais il peut perdre silencieusement les éléments qui intéressent les développeurs : les éléments de réponse, l'état côté serveur, les appels d'outils, la continuité du raisonnement, les événements du cycle de vie du flux, la sémantique d'annulation et l'attribution d'utilisation au niveau de l'élément.
L'objectif pratique est une couche de compatibilité qui traite l'API Responses comme un protocole plus riche. Conservez la prise en charge des complétions de discussion pour les clients existants, mais créez des réponses comme sa propre surface de passerelle avec son propre modèle d'état, son propre normalisateur de flux, son registre d'appels d'outils, sa matrice de capacités et ses règles de secours.
Qu'est-ce que les faits, qu'est-ce que la politique et qu'est-ce que la prédiction ?
Faits : OpenAI décrit l'API Responses comme des fonctionnalités unificatrices qui étaient auparavant réparties entre les complétions de chat et les assistants, y compris la prise en charge d'outils tels que la recherche sur le Web, la recherche de fichiers et l'utilisation d'un ordinateur. L'API expose des champs tels que previous_response_id, le streaming, la sélection d'outils et les outils intégrés. La documentation du SDK montre que previous_response_id peut assurer la continuité de la conversation, tandis que les instructions précédentes ne sont pas automatiquement reportées et doivent être renvoyées lorsqu'elles devraient toujours s'appliquer. La référence de streaming d'OpenAI inclut un cycle de vie de réponse et des événements de sortie distincts plutôt que uniquement des deltas de jetons.
Recommandations : Une passerelle doit conserver ces sémantiques plutôt que de les aplatir par défaut. Il doit rejeter ou rétrograder explicitement les demandes lorsqu'un fournisseur cible ne peut pas prendre en charge le comportement requis.
Prédiction : l'augmentation des charges de travail des agents dépendra de la structure des éléments de réponse, des traces d'exécution des outils et du contexte de raisonnement avec état. Les passerelles qui modélisent ces concepts seront désormais plus faciles à étendre que les passerelles qui traitent les réponses comme un point final cosmétique.
Définir un contrat de compatibilité distinct pour les réponses
La première erreur d'implémentation est de supposer que la compatibilité avec OpenAI signifie un schéma universel de requête et de réponse. En pratique, /v1/chat/completions et /v1/responses devraient être des contrats de compatibilité distincts.
Conservez une couche partagée d'authentification, de facturation, de quota et de routage, mais séparez la couche de protocole :
- Surface des discussions terminées : messages, choix, deltas, appels d'outils au format chat, comportement des anciens clients.
- Affichage des réponses : éléments d'entrée, éléments de sortie, ID de réponse, références de réponse précédentes, événements d'outils plus riches, événements de flux de cycle de vie, champs liés au raisonnement et état de réponse final.
Cette répartition est importante pour les tests de conformité. Un adaptateur de fournisseur qui réussit les tests de discussion peut toujours échouer aux tests de réponses, car il ne peut pas conserver le previous_response_id, l'ordre des éléments, la structure de refus, les métadonnées des outils hébergés ou les noms d'événements de streaming.
Un contrat de compatibilité minimal devrait répondre :
- Quels champs de requête sont acceptés, rejetés, transformés ou ignorés ?
- Quels types d'éléments de réponse sont conservés ?
- Quels types d'outils sont pris en charge par fournisseur et par modèle ?
- Le fournisseur peut-il maintenir l'état de conversation ou la passerelle doit-elle le conserver ?
- Que se passe-t-il lorsque
store=falseest demandé ? - Quels événements de flux sont garantis ?
- Comment les annulations, les délais d'attente et les utilisations partielles sont-ils enregistrés ?
Si vous disposez déjà d'une passerelle API AI, traitez la prise en charge des réponses comme une extension de protocole et non comme un alias de route.
Utiliser un modèle d'élément de réponse canonique
L'API Responses renvoie plusieurs messages d'assistant. Il peut représenter différents éléments et événements de sortie. Votre passerelle a besoin d'un modèle canonique interne avant d'être mappée à un fournisseur.
Un schéma d'élément interne pratique peut commencer comme ceci :
{
"gateway_response_id": "gw_resp_...",
"provider_response_id": "resp_...",
"tenant_id": "ten_123",
"key_id": "key_456",
"model_alias": "agent-par défaut",
"provider": "openai",
"articles": [
{
"item_id": "item_1",
"type": "texte",
"rôle": "assistant",
"content": [{ "type": "output_text", "text": "..." }],
"statut": "terminé"
},
{
"item_id": "item_2",
"type": "appel_fonction",
"call_id": "call_abc",
"name": "lookup_order",
"arguments_json": "{\"order_id\":\"123\"}",
"statut": "terminé"
}
],
"utilisation": {
"input_tokens": 0,
"output_tokens": 0,
"reasoning_tokens": nul,
"tool_units": []
},
"statut": "terminé"
Incluez les types d'articles avant même que chaque fournisseur puisse les produire. Les catégories utiles incluent :
- Sortie de texte
- Refus
- Appels de fonctions
- Sorties de fonction soumises par l'application
- Résumés de raisonnement ou métadonnées liées au raisonnement, le cas échéant
- Références de fichiers
- Recherche sur le Web, recherche de fichiers, utilisation d'un ordinateur ou autres événements liés aux outils hébergés
- Métadonnées d'utilisation finale et de facturation
Le but n'est pas d'exposer un schéma propriétaire aux utilisateurs. L'objectif est d'empêcher la passerelle de jeter des informations avant de pouvoir les auditer, les facturer, les diffuser, les relire ou les transformer.
Créer un grand livre d'État appartenant à la passerelle
previous_response_id est le champ qui expose le plus la différence entre le proxy de chat sans état et la compatibilité des réponses. Si un client fait référence à une réponse précédente, la passerelle doit savoir ce que signifie cet ID, si le locataire est autorisé à l'utiliser et si le fournisseur peut continuer à partir de celui-ci.
Créez un grand livre d'état saisi par locataire et ID de réponse :
{
"gateway_response_id": "gw_resp_789",
"provider_response_id": "resp_provider_789",
"previous_gateway_response_id": "gw_resp_456",
"tenant_id": "ten_123",
"id_utilisateur": "utilisateur_999",
"key_id": "key_456",
"model": "gpt-...",
"provider": "openai",
"store_mode": "fournisseur|passerelle|aucun",
"retention_policy": "standard|zero_retention|custom_30d",
"instructions_hash": "sha256:...",
"tool_policy_id": "tools_readonly_v3",
"created_at": "...",
"expires_at": "...",
"deleted_at": nul
Règle importante : n'émulez pas automatiquement previous_response_id en rejouant l'historique complet des discussions, sauf si le locataire a explicitement autorisé ce comportement de rétention et de coût. La relecture peut augmenter le coût du jeton, modifier la posture de confidentialité et modifier le comportement du modèle. Il est plus sûr de renvoyer une erreur de capacité claire que d'envoyer silencieusement le contenu de conversation stocké que l'application ne s'attend pas à ce que vous le conserviez ou le réutilisiez.
Modes de gestion des états
- État du fournisseur : le fournisseur en amont stocke suffisamment de contexte et la passerelle mappe les ID de réponse de la passerelle aux ID de réponse du fournisseur.
- État de la passerelle : la passerelle stocke les éléments antérieurs nécessaires et reconstruit le contexte lorsque cela est autorisé.
- Aucun état : la demande utilise
store=falseou la stratégie du locataire interdit la conservation.previous_response_iddoit être rejeté, sauf si le fournisseur peut honorer la demande sans rétention de passerelle et que la politique le permet.
N'oubliez pas non plus que les instructions précédentes peuvent devoir être renvoyées par le client alors qu'elles doivent continuer à s'appliquer. La passerelle ne doit pas inventer d'instructions cachées pour compenser, à moins que ce comportement ne fasse partie d'une politique explicite de locataire.
Valider les outils avant expédition
Les réponses rendent l'utilisation des outils plus centrale. Une couche de compatibilité doit gérer deux grandes catégories :
- Outils d'application : définitions de fonctions fournies par le client, exécutées en dehors du fournisseur de modèles, avec des sorties renvoyées à l'API.
- Outils du fournisseur hébergé : recherche sur le Web, recherche de fichiers, utilisation de l'ordinateur, exécution de code, mise à la terre ou outils similaires exécutés par le fournisseur ou l'infrastructure contrôlée par la passerelle.
À l'entrée, validez les schémas d'outils avant le routage :
- Rejeter rapidement le schéma JSON non valide.
- Imposer la taille maximale du schéma et la profondeur d'imbrication.
- Vérifiez les noms des outils pour vérifier la compatibilité des fournisseurs.
- Appliquer les étendues de locataire, de clé, d'utilisateur et d'environnement.
- Exiger des portes d'approbation pour les outils qui écrivent des données, dépensent de l'argent, accèdent à des systèmes sensibles ou appellent des connecteurs externes.
Pour les appels de fonctions d'application, exigez un ID d'appel stable. Le modèle émet un appel de fonction avec call_id ; l'application soumet la sortie de l'outil faisant référence à cet ID ; la passerelle enregistre les deux dans la même trace. Sans cette clé de jointure, les journaux d'audit et les tentatives deviennent ambigus.
Pour les outils hébergés, réservez le budget avant l'expédition et réglez les coûts ensuite. Les outils hébergés peuvent ajouter des frais en dehors de la comptabilité ordinaire des jetons, alors connectez le grand livre de l'outil à la facturation unifiée de l'API IA plutôt que de cacher ces coûts dans un total générique d'appel de modèle.
Normaliser le streaming sous forme d'événements, et non de texte de jeton
Un proxy de chat peut souvent s'en sortir en transférant des deltas de jetons. Une passerelle Responses ne le peut pas. Le flux a une signification de cycle de vie : une réponse peut démarrer, les éléments de sortie peuvent démarrer et se terminer, le texte peut arriver sous forme de deltas, les appels d'outils peuvent être assemblés de manière incrémentielle, l'utilisation peut arriver à la fin ou pendant le flux, et la réponse peut échouer ou être annulée.
Définissez un schéma d'événement de passerelle, puis mappez-y chaque flux de fournisseur :
événement : response_started
données : { "response_id": "gw_resp_123", "status": "in_progress" }
événement : output_item_starteddonnées : { "item_id": "item_1", "type": "text" }
événement : text_delta
données : { "item_id": "item_1", "delta": "Bonjour" }
événement : tool_call_delta
données : { "item_id": "item_2", "call_id": "call_abc", "arguments_delta": "{\"order" }
événement : utilisation_delta
données : { "output_tokens": 12 }
événement : terminé
données : { "response_id": "gw_resp_123", "usage": { ... } }
Événements normalisés recommandés :
response_startedoutput_item_startedoutput_item_completedtext_deltarefusal_deltatool_call_deltatool_result_receivedusage_deltaterminéannulééchec
Lorsque le client se déconnecte, propagez l'annulation en amont si le fournisseur le prend en charge. Enregistrez l’état de réponse partielle dans les deux cas. Si le fournisseur renvoie ultérieurement l'utilisation finale via un rappel différé ou un morceau final, rapprochez le grand livre. La compatibilité du streaming concerne autant la comptabilité et le cycle de vie que la latence.
Créer une matrice de capacités du fournisseur
Le routage multimodèle n'est utile que lorsque la passerelle comprend ce qui peut être acheminé en toute sécurité. Ajoutez des fonctionnalités spécifiques aux réponses à votre catalogue de modèles :
{
"model_alias": "agent-par défaut",
"itinéraires": [
{
"provider": "openai",
"modèle": "...",
"supports_responses": vrai,
"supports_previous_response_id" : vrai,
"supports_store_false" : vrai,
"supports_builtin_web_search": vrai,
"supports_function_calling": vrai,
"supports_stream_lifecycle_events" : vrai,
"supports_reasoning_context_continuity" : vrai,
"max_tool_schema_bytes": 65536
},
{
"fournisseur": "provider_b",
"modèle": "...",
"supports_responses": faux,
"chat_adapter_available": vrai,
"loss_profile": ["no_previous_response_id", "no_hosted_tools", "flattened_stream"]
}
]
La solution de secours doit tenir compte des pertes. Si la demande nécessite une recherche Web intégrée et que le fournisseur de secours ne peut pas l'exécuter, ne répondez pas silencieusement sans effectuer de recherche. Si la requête dépend d'un contexte de raisonnement préservé et que la route de secours ne peut pas le préserver, renvoie une erreur de capacité ou une réponse de rétrogradation à laquelle le client a explicitement opté.
Une option de requête utile est :
{
"model": "agent-par défaut",
"entrée": "...",
"fallback_policy": {
"allow_lossy": faux,
"allowed_losses": []
}
Pour les cas d'utilisation moins sensibles, les locataires peuvent autoriser des rétrogradations spécifiques avec perte :
{
"fallback_policy": {
"allow_lossy": vrai,
"allowed_losses": ["flattened_stream", "no_reasoning_summary"]
}
La passerelle doit enregistrer la décision de secours dans les deux cas. Cela rend possible un débogage ultérieur lorsqu'un agent se comporte différemment après une panne de fournisseur ou une redirection de modèle.
Utilisation des attributs au niveau de la réponse et de l'élément
Les appels de réponse peuvent coûter plus cher que les appels de chat équivalents, car ils peuvent inclure l'exécution d'un outil, un contexte plus long, des jetons de raisonnement, une recherche de fichiers, une recherche sur le Web ou des instructions répétées. Un seul nombre global de jetons n'est pas suffisant pour un tableau de bord d'analyse de l'utilisation de l'API IA.
Enregistrer l'utilisation à deux niveaux :
- Niveau de réponse : locataire, clé, utilisateur, modèle, fournisseur, latence, état final, jetons d'entrée, jetons de sortie, jetons de raisonnement lorsqu'ils sont signalés, coût total et itinéraire de secours.
- Niveau de l'élément/de l'outil : nom de l'outil, ID d'appel, unités d'outils hébergées, ID de fichier, nombre de requêtes de recherche si disponible, latence de l'outil, coût de l'outil et résultat de la politique d'approbation.
Cela permet aux développeurs de répondre à des questions concrètes :
- Le coût a-t-il augmenté en raison d'un état plus long, d'un effort de raisonnement, d'appels d'outils ou d'une solution de secours ?
- Quel locataire ou clé API génère des frais pour les outils hébergés ?
- Quelle réponse a échoué après un appel d'outil mais avant le texte final ?
- Quels flux annulés ont néanmoins nécessité une utilisation en amont ?
Gérer la rétention zéro et la suppression comme comportement de première classe
L'état côté serveur est utile, mais il modifie les obligations de conservation de la passerelle. Intégrez une stratégie dans la couche de protocole au lieu de la traiter comme un paramètre de journalisation.
Pour chaque demande de réponses, résolvez :
- Règles de fidélisation des locataires
- Préférence
magasinau niveau de la requête - Compatibilité de rétention des fournisseurs
- Si la relecture de la passerelle est autorisée
- Si les entrées et sorties de l'outil peuvent être stockées
- Comportement d'expiration et de suppression pour l'état de réponse
Si la rétention est désactivée, la passerelle peut toujours conserver un minimum de métadonnées opérationnelles : horodatages, identifiants, statut, nombre de jetons, coût et décisions politiques. Évitez de stocker des invites brutes, des résultats complets d'outils ou un historique reconstruit, sauf si la politique le permet.
Modules de conformité à ajouter avant le lancement
Ne vous fiez pas aux tests manuels Happy Path. Ajoutez des appareils qui vérifient le comportement du protocole sur les routes OpenAI directes, les routes adaptées au fournisseur et les scénarios de secours.
Ensemble de tests minimum
- Réponse de base : l'élément de texte est renvoyé avec un ID de réponse et une utilisation stables.
- État multi-tours : la deuxième requête fait référence à
previous_response_id; la passerelle valide la propriété du locataire et le mode d'état. - Instructions répétées : vérifiez que les instructions omises ne sont pas inventées silencieusement par la passerelle.
- Fonction appel aller-retour : le modèle émet un identifiant d'appel ; l'application soumet le résultat ; la réponse finale joint les deux enregistrements.
- Règle relative aux outils hébergés : l'outil intégré non autorisé est bloqué avant son expédition.
- Ordre de diffusion : le début de la réponse, le début de l'élément, les deltas, l'achèvement de l'élément, l'utilisation et l'achèvement sont émis dans un ordre valide.
- Annulation du flux : la déconnexion du client déclenche une annulation en amont lorsque cela est pris en charge et enregistre une utilisation partielle.
- Rejet de secours : le fournisseur sans la sémantique des réponses requises renvoie une erreur de capacité.
- Activation du remplacement avec perte : la demande avec des pertes autorisées reçoit un marqueur de déclassement explicite.
- Mode de rétention zéro : la relecture de l'état et la conservation des invites côté passerelle sont bloquées.
Séquence de déploiement recommandée
- Exposer une route bêta. Ajoutez
/v1/responsessans modifier le comportement de chat existant. - Implémentez d'abord l'intercommunication pour les fournisseurs prenant en charge les réponses natives. Préservez les ID, les éléments, les flux, l'utilisation et les erreurs.
- Ajoutez le grand livre d'état. Mappez les ID de passerelle aux ID de fournisseur et imposez la propriété des locataires.
- Ajoutez des éléments canoniques. Stockez les métadonnées des éléments nécessaires à l'audit, à la facturation et à la reconstruction du flux.
- Ajoutez une gouvernance d'outil. Validez les schémas, appliquez des portées et enregistrez les jointures d'appel d'outil.
- Ajoutez une normalisation du streaming. Convertissez les flux spécifiques au fournisseur en événements de cycle de vie de passerelle.
- Ajouter un routage prenant en compte les capacités. Autoriser uniquement les solutions de secours sécurisées par défaut.
- Ajoutez des analyses et un règlement de facturation. Attribuez séparément le jeton d'attribut, le raisonnement et l'utilisation de l'outil.
- Publiez des notes de compatibilité. Indiquez aux développeurs quels champs sont natifs, émulés, non pris en charge ou avec perte.
Conclusion exploitable
Une couche de compatibilité API Responses doit préserver la signification du protocole, et pas simplement renvoyer un texte plausible. Construisez-le autour de cinq objets durables : un modèle d'élément de réponse canonique, un registre d'état de conversation, un registre d'appels d'outils, un normalisateur d'événements de streaming et une matrice de capacités de fournisseur.
La valeur par défaut la plus sûre est la compatibilité stricte : si une route ne peut pas préserver l'état requis, les outils, le contexte de raisonnement, les événements de flux ou le comportement de rétention, renvoie une erreur de capacité claire. Ajoutez une solution de secours avec perte opt-in uniquement lorsque les développeurs comprennent ce qui sera supprimé. Cette approche peut sembler moins pratique que l'aplatissement automatique, mais elle évite le pire mode de défaillance : une application qui semble compatible tout en perdant silencieusement la sémantique qui lui a fait utiliser l'API Responses en premier lieu.