Assistants API a été officiellement arrêtée le 26 août 2026 et n’est plus disponible. Les applications doivent déplacer génération, état, outils et données vers Responses API. Inventoriez chaque Assistant, Thread, Run et outil, reconstruisez la configuration, importez l’historique détenu par l’application, puis testez les réponses et effets de bord avant le basculement. La date et la correspondance figurent dans le guide officiel de migration Assistants d’OpenAI.
Ce que change l’arrêt du 26 août 2026
Il s’agit d’une migration de points de terminaison et d’objets, pas d’un changement de nom de modèle. Après l’arrêt, les appels aux anciennes ressources Assistants ne sont plus un avertissement. Le code qui lit /v1/assistants, /v1/threads, /v1/threads/messages ou /v1/threads/runs doit changer de chemin. Ne démarrez pas d’intégration avec l’ancienne API et ne supposez pas que ses objets resteront interrogeables.
La correspondance actuelle publiée par OpenAI est la suivante :
| Assistants API | Plateforme Responses | Sens pratique |
|---|---|---|
| Assistant | Prompt ou configuration de requête | Conservez le modèle, les instructions, les déclarations d’outils et les règles de sortie dans une configuration versionnée. Le guide actuel permet de créer un Prompt depuis un assistant dans le tableau de bord, mais signale aussi la dépréciation des objets Prompt réutilisables. |
| Thread | Conversation ou historique de l’application | Une Conversation contient des éléments, notamment des messages, des appels d’outils et leurs résultats. Vous pouvez également conserver l’état dans votre base et envoyer les éléments nécessaires. |
| Run | Response | Une requête Responses reçoit des éléments d’entrée et renvoie des éléments de sortie. L’objet Run et son cycle d’interrogation ne sont plus l’abstraction centrale. |
| Run step | Item | Traitez les éléments typés message, function_call, function_call_output et reasoning, sans supposer que chaque résultat est un message. |
Consultez le guide de migration vers Responses API en parallèle du guide d’arrêt. Il présente Responses comme l’API recommandée pour les nouveaux projets et décrit les différences avec Chat Completions ainsi que les formats d’entrée et de sortie.
Le nouveau modèle mental
Un Assistant était un ensemble de paramètres persistant. Un Thread conservait les messages et un Run exécutait l’Assistant. Responses sépare ces responsabilités. La requête définit modèle, instructions, entrée et outils. Le résultat est un Response typé dont output est une liste ordonnée d’éléments.
Cette conception laisse l’orchestration à l’application. Le code détermine identité, historique, appels autorisés, validation, reprises et approbation humaine. Les options d’état sont choisies par le produit, pas imposées par un cycle de vie caché d’Assistant.
Trois stratégies d’état sont utiles :
- Envoyez une requête sans état et une liste limitée à chaque tour. Votre base contrôle conservation et élagage.
- Enchaînez les tours avec previous_response_id. Le guide de l’état des conversations présente ce modèle. Les jetons précédents restent facturés et la conservation doit respecter votre politique.
- Créez un objet Conversations API et transmettez son ID à Responses. Une Conversation possède un identifiant durable entre sessions, appareils ou tâches. Ses éléments restent jusqu’à suppression, donc l’ID n’est pas un interrupteur de confidentialité.
Choisissez une stratégie par flux fonctionnel. Ne mélangez pas un historique reconstruit localement, une Conversation et une chaîne previous_response_id sans définir une source de vérité. Les tours dupliqués peuvent modifier le comportement du modèle, augmenter les coûts et compliquer les demandes de suppression.
Inventoriez avant de modifier le code
Créez une fiche pour chaque Assistant ID et parcours de session. Notez modèle, instructions, paramètres, schémas, vector stores, fichiers, Code Interpreter, format, métadonnées, conservation et code qui interroge Run. Cherchez aussi dans tâches, scripts, tableau de bord, tests et analytique. Une réponse réussie ne prouve pas que file search, sortie structurée, streaming ou fonctions à effet de bord restent identiques.
Séparez comportement et données. Les instructions et outils se recréent depuis la configuration. Messages de Threads et fichiers exigent une copie détenue par l’application. Le guide postérieur à l’arrêt indique que récupérer d’anciens messages Thread ne fonctionne plus.
Recréez la requête de base
Pour un échange textuel, remplacez beta Thread et Run par un appel Responses. input accepte une chaîne ou une liste d’éléments. Utilisez instructions pour le comportement système et gardez le texte utilisateur dans input. Lisez via response.output_text, mais inspectez response.output si des outils ou éléments non textuels sont possibles.
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-5.6",
instructions="Répondez clairement et citez les dossiers fournis.",
input=[{"role": "user", "content": "Résumez l’état de la commande."}],
store=False,
)
print(response.output_text)
Le nouveau point de terminaison est /v1/responses et la méthode SDK est client.responses.create. N’utilisez pas messages, choices[0].message.content ni une boucle de Runs. Si Responses doit être conservé, décidez-le explicitement. La documentation sur les contrôles des données indique une conservation de l’état Responses de 30 jours par défaut ou avec store=true, avec exceptions.
Préservez correctement l’historique
Si votre application possède la transcription, normalisez-la en éléments d’entrée Responses. Un texte utilisateur devient input_text, un texte d’assistant devient output_text et une image devient input_image avec son URL ou sa référence de fichier. Conservez l’ordre chronologique ainsi que les paires appel d’outil et résultat nécessaires à la compréhension d’un tour antérieur.
Cet exemple crée une Conversation durable depuis un historique détenu par l’application, puis envoie un nouveau tour :
from openai import OpenAI
client = OpenAI()
conversation = client.conversations.create(
items=[
{
"role": "user",
"content": [{"type": "input_text", "text": "Ma commande est 1842."}],
},
{
"role": "assistant",
"content": [{"type": "output_text", "text": "Je peux vérifier la commande 1842."}],
},
]
)
response = client.responses.create(
model="gpt-5.6",
conversation=conversation.id,
input=[{"role": "user", "content": "Est-elle prête à être expédiée ?"}],
)
print(response.output_text)
Après l’arrêt, ne tentez pas de migrer avec threads.messages.list. Un système postérieur doit utiliser les données conservées par l’application. Avant l’import, rapprochez l’identité, les demandes de suppression, les règles régionales, les pièces jointes et les horodatages, puis vérifiez que chaque Conversation ID appartient à l’utilisateur authentifié.
Déplacez les outils et les appels de fonctions
Les outils Responses sont déclarés dans la requête. Les outils intégrés comme web search, file search, computer use, Code Interpreter, la génération d’images et MCP distant sont décrits dans Using tools. Les fonctions personnalisées doivent toujours être implémentées par l’application. Le modèle peut demander une fonction, mais il ne peut ni autoriser ni exécuter votre opération métier.
La boucle de contrôle est explicite. Envoyez la première requête, inspectez response.output pour les éléments function_call, validez et exécutez chaque fonction autorisée, ajoutez les éléments de sortie du modèle et les éléments function_call_output, puis envoyez la requête suivante. Pour les modèles de raisonnement, conservez les éléments reasoning renvoyés avec un appel, comme le montre le guide des appels de fonctions.
import json
from openai import OpenAI
client = OpenAI()
tools = [
{
"type": "function",
"name": "lookup_order",
"description": "Retourner le statut d’une commande appartenant à l’utilisateur authentifié.",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
},
"required": ["order_id"],
"additionalProperties": False,
},
"strict": True,
}
]
input_items = [{"role": "user", "content": "Où est ma commande 1842 ?"}]
response = client.responses.create(
model="gpt-5.6",
tools=tools,
input=input_items,
)
input_items += response.output
for item in response.output:
if item.type == "function_call" and item.name == "lookup_order":
arguments = json.loads(item.arguments)
result = {"order_id": arguments["order_id"], "status": "packed"}
input_items.append(
{
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps(result),
}
)
response = client.responses.create(
model="gpt-5.6",
tools=tools,
input=input_items,
)
print(response.output_text)
Le mode strict aide à respecter le schéma, mais ne fournit aucune autorisation. Vérifiez dans le code l’utilisateur, la propriété de la commande, les plages, les valeurs enum et l’état métier. Pour un paiement, une suppression, une publication ou un envoi, utilisez l’idempotence ou une transaction. En cas d’échec, renvoyez une erreur d’outil structurée au lieu de simuler le succès. Limitez le nombre de tours d’outils et enregistrez les appels, résultats et approbations après masquage des valeurs sensibles.
Conservez les sorties structurées
Si l’ancien Assistant utilisait le mode JSON ou un schéma de réponse, mappez-le vers la configuration Responses text.format au lieu de recopier response_format. Le guide des sorties structurées décrit la forme actuelle du schéma et les aides SDK. Validez le résultat analysé avant de l’envoyer à une base, une interface ou un autre outil. Un document JSON valide peut contenir un numéro de commande incorrect, une instruction dangereuse ou une décision métier incomplète.
Gardez le schéma réduit et versionnez-le avec le Prompt ou la configuration. Déclarez les champs obligatoires, utilisez additionalProperties=false quand le mode strict l’exige et testez les refus, les réponses incomplètes et les changements. Un objet JSON seul ne prouve jamais la réussite.
Sécurité et données après la migration
La migration change la frontière de l’état, donc elle doit être revue comme un changement d’architecture de sécurité. Gardez les clés API sur un serveur de confiance, authentifiez chaque session et liez une Conversation ou une transcription locale à l’identité serveur. Ne placez pas de secrets, de jetons d’autorisation ou de requêtes de base sans restriction dans les instructions ou les descriptions d’outils.
Utilisez le minimum d’outils, séparez lecture et écriture, exigez une confirmation et autorisez hors du modèle. Considérez fichiers, pages et réponses MCP comme non fiables. MCP a sa propre conservation et Code Interpreter peut garder un état temporaire. Le guide des contrôles des données détaille ces limites.
Choisissez store, une Conversation ou une transcription détenue par l’application pour chaque flux. Les données API ne servent pas à entraîner les modèles OpenAI sans consentement explicite, mais cela ne remplace pas l’examen de la conservation, des accès, de la suppression, du traitement régional et des fournisseurs. store=false n’est pas une politique générale de suppression et ne rend pas une Conversation éphémère.
Limitez les entrées et sorties, utilisez la modération quand elle est nécessaire et prévoyez une revue humaine pour les décisions à fort impact. Les bonnes pratiques de sécurité d’OpenAI recommandent des tests adversariaux contre l’injection de prompt, la modération et la supervision humaine. Journalisez les ID de requête et les types d’événements, mais masquez le contenu utilisateur, les identifiants, les arguments de fonctions et les résultats d’outils selon votre politique.
Erreurs fréquentes de migration
L’ancien point de terminaison renvoie une erreur
Après le 26 août 2026, les requêtes vers Assistants indiquent un défaut de migration. Supprimez l’ancien chemin client au lieu de le réessayer. Si un worker interroge encore des Run ID, déployez le worker Responses et remplacez les champs thread_id et run_id par les identifiants de session et de Response.
La réponse est vide ou le parseur échoue
La sortie Responses est une liste hétérogène. output_text convient au texte ordinaire, mais un appel d’outil, un refus ou une réponse incomplète exige de vérifier le statut et les types d’éléments. N’indexez jamais le premier élément en supposant qu’il s’agit d’un message.
Le modèle répète le contexte ou les coûts augmentent
Choisissez une stratégie d’état et une règle d’élagage. previous_response_id ne rend pas gratuits les anciens jetons d’entrée et copier la même transcription dans une Conversation et dans input duplique le contexte. Mesurez les jetons entrants et sortants en staging avec des conversations longues réalistes.
Une fonction s’exécute deux fois
Les reprises, appels parallèles, délais réseau et reconnexions peuvent rejouer un appel. Donnez à chaque opération à effet de bord une clé d’idempotence fondée sur le call ID et l’utilisateur authentifié, puis vérifiez la transaction métier avant de l’appliquer. Un message réussi du modèle ne prouve pas que la fonction n’a été exécutée qu’une fois.
Les anciens fichiers ou résultats de recherche disparaissent
Inventoriez les vector stores, ID de fichiers, expirations et permissions séparément de l’historique Thread. Recréez le parcours de recherche supporté, vérifiez l’accès de chaque locataire et testez les citations et les résultats vides. La conversion d’une configuration Assistant ne copie pas les fichiers.
Checklist de migration
Exécutez ces étapes dans l’ordre pour chaque flux de production :
- Notez les dépendances aux anciens Assistant, Thread, Run, fichiers, vector stores, outils, Prompt et métadonnées.
- Placez les instructions visibles par l’utilisateur et les schémas d’outils dans une configuration versionnée.
- Sélectionnez un modèle Responses et confirmez ses outils, entrées multimodales, sorties structurées et disponibilité régionale.
- Choisissez une seule stratégie d’état : éléments sans état, previous_response_id ou Conversations.
- Mappez messages vers input, choices vers output et l’extraction du texte vers output_text.
- Réécrivez les fonctions et implémentez une boucle d’outils explicite et limitée.
- Rétablissez séparément file search, Code Interpreter, web search, MCP, streaming et les sorties structurées.
- Importez uniquement l’historique détenu par l’application en conservant ordre, identités, pièces jointes, appels et suppressions.
- Ajoutez autorisation, limites d’entrée, modération, idempotence, journaux masqués et approbation des effets de bord.
- Lancez des conversations de référence, des prompts adversariaux, des erreurs d’outils, des reprises, des refus, de longs contextes et des sessions concurrentes.
- Comparez les réponses, citations, effets d’outils, jetons, latence, erreurs et conservation.
- Déployez derrière un feature flag, arrêtez les anciens workers, surveillez les erreurs Responses et gardez un repli sans l’API arrêtée.
- Supprimez l’ancien code Assistant et les clés seulement après vérification des exports, de l’audit et du support.
Pour la conception du système, consultez le guide d’architecture d’un agent IA en production. Pour les jeux de régression et les contrôles comportementaux, consultez le guide des évaluations d’agents IA.
Comment vérifier la fin de la migration
La migration est terminée lorsqu’aucun parcours ne dépend des ressources Assistants, que chaque session possède un propriétaire d’état, que chaque appel d’outil est autorisé et résiste aux rejouements, et que la sortie Responses est testée. Conservez versions, décisions de conservation et échecs. Réexaminez la fiche lorsque Responses ou le modèle évolue, car l’arrêt de l’ancien repli n’élimine pas l’évaluation continue.