Tutoriel API GPT-6 Sol : créer un agent de migration de codebase
Apprenez à utiliser l’API GPT-6 Sol en Python. Créez un agent de migration de codebase avec des outils de dépôt, des Structured Outputs, un triage GPT-6 Luna, du pilotage et pytest.
Ici, nous allons utiliser GPT-6 Sol pour migrer Northstar Checkout, un petit service de paiement Python fictif, d’un adaptateur de paiement local v1 vers v2.
Plus précisément, nous verrons comment :
Effectuer un premier appel à l’API GPT-6 Sol et lire ses champs d’usage
Définir le contrat de migration avant que le modèle ne voie le dépôt
Donner à GPT-6 Sol des outils de fichiers et de tests restreints, puis échelonner les accès avec allowed_tools
Utiliser GPT-6 Luna pour le triage et faire vérifier la présélection par GPT-6 Sol
Renvoyer un plan de migration structuré et le confronter aux fichiers déjà lus par GPT-6 Sol
Lancer la migration via WebSocket et la piloter après le début des éditions
Augmenter l’effort de raisonnement après l’échec d’une sonde de déploiement indépendante
Calculer le coût enregistré à partir de l’usage API
Ce que j’ai appris en chemin
Quatre constats ont changé ma façon d’aborder la prochaine version :
Réussir la suite d’acceptation ne suffisait pas. Envoyer la même requête de paiement à un autre serveur exposait toujours une exception brute de l’adaptateur.
L’augmentation d’effort avait un vrai déclencheur. Après l’échec de la sonde de déploiement, GPT-6 Sol a trouvé le bug dans l’état conservé par un processus et a réparé les relances entre serveurs.
Un pilotage ne peut pas annuler une édition, mais le modèle, si. GPT-6 Sol avait déjà renommé un paramètre public quand la nouvelle exigence est arrivée, et il a annulé ce renommage.
La présélection de GPT-6 Luna couvrait tout, mais ses gains restent à prouver. GPT-6 Sol a tout de même étendu la recherche avant de planifier.
Qu’est-ce que GPT-6 Sol ?
GPT-6 Sol est le niveau intermédiaire de la famille GPT-6 d’OpenAI, et l’ID du modèle dans l’API est gpt-6-sol. Notre guide des niveaux de modèles GPT-6 couvre le lancement et les benchmarks. Les recommandations GPT-6 d’OpenAI placent GPT-6 Astra en premier, GPT-6 Sol au milieu, et GPT-6 Luna au coût le plus bas.
GPT-6 Sol offre une fenêtre de contexte de 1 050 000 tokens et peut renvoyer jusqu’à 128 000 tokens en sortie. L’effort de raisonnement va de none à max et la valeur par défaut est medium. Chat Completions ne prend en charge l’appel de fonctions de GPT-6 Sol qu’avec none, donc toutes les requêtes ici utilisent la Responses API.
La tarification et les capacités de l’API déterminent la façon dont le harnais envoie chaque requête.
Combien coûte l’API GPT-6 Sol ?
GPT-6 Sol coûte 2 $ par million de tokens en entrée et 10 $ par million de tokens en sortie pour des requêtes allant jusqu’à 272 000 tokens en entrée, d’après la page de tarification d’OpenAI. L’entrée mise en cache coûte 0,20 $ par million, et l’écriture en cache 2,50 $. Les tarifs de GPT-6 Luna pour ces quatre catégories sont 0,10 $, 0,01 $, 0,125 $ et 0,50 $.
Au-delà de 272 000 tokens en entrée, toute la requête est facturée à 2× les tarifs d’entrée et de cache, et 1,5× le tarif de sortie. Aucune requête de ce projet ne s’en est approchée.
Quelles fonctionnalités de l’API ce tutoriel utilise-t-il ?
Le harnais, c’est-à-dire le code Python autour du modèle, utilise ces contrôles de GPT-6 :
Ces quatre contrôles restent dans la même chaîne de réponses de la Responses API.
Qu’allons-nous construire avec l’API GPT-6 Sol ?
Nous allons créer un agent qui fait passer Northstar Checkout de Payments Adapter v1 à v2. Les deux adaptateurs sont des remplaçants locaux écrits pour cette expérience, pas de vrais SDK de paiement. Le code complet, les fixtures et l’exécution enregistrée se trouvent dans ce dépôt GitHub.
Le dépôt mêle du code de paiement à des modules sans lien, donc GPT-6 Sol doit trouver lui-même les fichiers concernés. La v2 rompt quatre contrats d’adaptateur :
La création d’un paiement passe de client.charge(...) à client.payments.create(...)
Les dictionnaires de résultats deviennent des objets typés avec des montants Money
Les cartes refusées renvoient un état au lieu de lever une exception
Les webhooks changent de nom, d’enveloppe et d’en-tête de signature
Une recherche/remplacement gère le renommage de méthode. Elle ne gère aucune des évolutions de comportement.
Une boucle de migration, deux modèles GPT-6. Image de l’auteur.
GPT-6 Sol reçoit le cahier des charges, l’arborescence des fichiers et des outils restreints qui deviennent appelables par étapes. Il ne sait ni quels fichiers doivent changer, ni qu’une exigence va évoluer.
Pourquoi cette migration d’API est-elle difficile ?
Deux parties des spécifications sont piégeuses. Ce ne sont pas des bugs plantés ; elles résultent de la rencontre du comportement v2 avec le code existant :
Idempotence. v2 compare les paramètres lorsqu’elle voit un request_id répété, mais le checkout place un nouvel order_id dans les métadonnées à chaque tentative, de sorte qu’une relance naïve est rejetée au lieu d’être dédupliquée.
Totaux des remboursements. le webhook payment.refunded de v2 rapporte le total remboursé à date, tandis que l’ancien gestionnaire additionne chaque valeur avec +=.
Les deux passent le contrôle de types. Vous ne les détectez qu’en exécutant l’enchaînement complet du checkout et des remboursements.
Les changements de paiement touchent plusieurs modules Northstar. Image de l’auteur.
La carte sépare les imports directs de l’adaptateur des modules dépendant du comportement de paiement. Ces liens indirects expliquent pourquoi un corrigé couvrant tout le dépôt compte.
Comment testerons-nous la migration ?
Une suite d’acceptation isolée, écrite avant tout appel au modèle, tranche le résultat. GPT-6 Sol ne la voit jamais ; le harnais l’exécute avec pytest sur la copie migrée. Elle vérifie que :
Le checkout réussit via v2, et une relance avec la même clé d’idempotence ne facture qu’une fois
Une carte refusée lève toujours l’erreur publique CheckoutDeclined
Un remboursement total, deux remboursements partiels et un webhook réémis laissent des totaux corrects
CheckoutClient conserve les mêmes signatures de méthodes
Aucune référence v1 ne subsiste, vendor/ et MIGRATION.md sont intacts, et les tests visibles passent
Le code d’origine passe déjà les contrôles d’interfaces inchangées et de fichiers protégés ; les autres vérifications mesurent la migration. Un corrigé séparé liste les changements requis, mais seul le harnais le lit.
Les répertoires acceptance/ et probes/ sont hors de la copie du dépôt exposée aux deux modèles. Le corrigé se trouve sous acceptance/, il ne peut donc pas entrer dans l’entrée de GPT-6 Luna, l’arborescence, ni aucun outil du dépôt.
La porte de lecture peut renvoyer des chemins issus du propre plan de GPT-6 Sol. La couverture du corrigé est enregistrée à des fins d’évaluation uniquement ; elle ne renvoie jamais à GPT-6 Sol des chemins manquants issus du terrain.
Une sonde de déploiement s’exécute après cette suite. Aucun de ces contrôles n’accepte le message « done » du modèle comme preuve.
Comment configurer l’API GPT-6 Sol en Python
Vous avez besoin de Python 3.10 ou plus récent et d’une clé API avec accès aux deux modèles. Les dépendances incluent l’extra realtime nécessaire au pilotage :
git clone https://github.com/KhalidAbdelaty/gpt-6-sol-api.git
cd gpt-6-sol-api
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install-r requirements.txt
Copy-Item .env.example .envPropulsé par
Sur macOS ou Linux, utilisez source .venv/bin/activate et cp .env.example .env, puis mettez OPENAI_API_KEY=... dans .env.
Si votre clé fonctionne déjà avec la Responses API, passez la section suivante.
Effectuez votre premier appel à l’API GPT-6 Sol
La plus petite requête utile confirme la clé, l’ID du modèle et les champs d’usage nécessaires à la section coût :
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI()
response = client.responses.create(
model="gpt-6-sol",input="In one sentence, why is a breaking API migration harder than renaming a function?",)print(response.reasoning.effort, response.output_text)print(response.usage)Propulsé par
La réponse indique un effort medium, et usage comprend cached_tokens et cache_write_tokens. Laissez de côté temperature et top_p. Les deux renvoient un 400 dès lors que l’effort n’est pas none.
Le premier appel GPT-6 Sol renvoie l’usage. Image de l’auteur.
Avec quel effort de raisonnement démarrer ?
Commencez à medium, la valeur par défaut, et gardez ce réglage au niveau de la requête tout au long de l’exécution. La plupart des tours de migration sont des lectures et de petites éditions. La sonde de déploiement fournit plus tard une raison d’augmenter l’effort.
Comment ajouter des outils de dépôt sûrs à un agent de code
La couche d’outils détient les permissions de l’agent. GPT-6 Sol reçoit ces outils-fonctions avec strict: true :
list_files et search_code localisent le code pertinent
read_file renvoie un fichier du dépôt
edit_file modifie une occurrence exacte
run_tests exécute une cible pytest autorisée
Des schémas stricts vérifient la forme des arguments, pas la sécurité des chemins, donc Python fait respecter la frontière d’écriture :
READ_ONLY =("vendor/","MIGRATION.md","conftest.py")if write:if rel_posix.startswith(READ_ONLY)or rel_posix in READ_ONLY:raise ToolError(f"{rel_posix} is read-only")# the spec and both adaptersifnot rel_posix.startswith(("northstar/","tests/"))ornot rel_posix.endswith(".py"):raise ToolError("writes are limited to Python files under northstar/ and tests/")Propulsé par
Le chemin est résolu d’abord, donc ../ et les chemins absolus échouent. edit_file remplace une correspondance exacte, et run_tests n’accepte que des cibles sous tests/.
Le harnais renvoie un appel bloqué comme une sortie d’outil ERROR:, et la boucle continue. Notre guide d’ingénierie de harnais d’agent explique pourquoi ces contrôles doivent vivre dans le harnais plutôt que dans le prompt.
Comment tester la frontière des fichiers
Appelez chaque outil avec une entrée qu’il doit rejeter :
Un chemin contenant ..
Un chemin absolu
Une écriture sous vendor/
Une cible de test contenant une commande shell
Aucune ne doit passer. Une édition qui correspond à plus d’un emplacement doit demander plus de contexte, et garder les règles dans des fonctions personnalisées les met à un seul endroit testable.
Comment utiliser GPT-6 Luna pour le triage du dépôt
Le triage d’un dépôt est une classification ciblée : évaluer la pertinence de chaque fichier et citer les références v1.GPT-6 Luna reçoit cette tâche et rien d’autre, et s’exécute en premier, avant que GPT-6 Sol n’ait rien cherché.
classFileVerdict(BaseModel):
path:str
relevance: Literal["high","medium","low","none"]
legacy_references:list[str]
triage = client.responses.parse(model="gpt-6-luna",input=spec_and_all_files,
text_format=TriageResult)# a list of FileVerdictPropulsé par
L’entrée est le cahier des charges plus chaque fichier Python sous northstar/ et tests/. Tout ce qui est noté high ou medium alimente la présélection que reçoit ensuite GPT-6 Sol.
Comment vérifier la présélection de GPT-6 Luna
Comparez la présélection avec le corrigé établi plus tôt, et regardez d’abord le rappel. GPT-6 Luna a conservé tous les fichiers affectés et ajouté quelques fichiers qui n’avaient pas besoin de changements.
GPT-6 Luna réduit de 56 à 16. Image de l’auteur.
Une présélection est une piste, pas une frontière.
Comment utiliser allowed_tools pour des permissions échelonnées
allowed_tools est un mode de tool_choice qui limite les outils que le modèle peut appeler, tout en gardant la liste complète en place. C’est ainsi que le premier passage de GPT-6 Sol reste en lecture seule : la liste complète est définie à chaque requête, mais seules la liste et la recherche sont appelables.
defallowed(names):return{"type":"allowed_tools","mode":"auto","tools":[{"type":"function","name": n}for n in names]}
response = client.responses.create(
model="gpt-6-sol", instructions=INSTRUCTIONS, tools=TOOLS,# full list, every time
tool_choice=allowed(["list_files","search_code"]),
reasoning={"effort":"medium"},input=inspect_prompt, store=True,)Propulsé par
Changer tools entre les phases réécrit le préfixe mis en cache. Le guide d’appel de fonctions recommande allowed_tools lorsque seul le sous-ensemble appelable doit changer.
Pourquoi démarrer un agent de code en lecture seule ?
Un passage en lecture seule sépare le diagnostic de l’action. GPT-6 Sol a reçu la présélection de GPT-6 Luna avec un simple avertissement qu’elle pouvait être erronée, et ses recherches d’imports v1, d’appels charge et de noms de webhooks ont, à elles seules, fait remonter tous les fichiers concernés.
Il est aussi allé au-delà de la liste, signalant les modèles de commande, le store de commandes, les sérialiseurs et l’export du grand livre comme dépendances aval à vérifier. Aucun n’a finalement nécessité de changement, mais les lire est la seule façon de le savoir. Je garderais allowed_tools pour tout agent qui édite des fichiers.
Comment utiliser Structured Outputs pour un plan de migration
Le plan de migration est l’endroit où l’agent s’engage sur des fichiers précis avant d’obtenir les droits d’écriture. La planification ajoute read_file, et le plan revient via Structured Outputs avec les outils coupés :
plan = client.responses.parse(
model="gpt-6-sol", instructions=INSTRUCTIONS, tools=TOOLS, tool_choice="none",
reasoning={"effort":"medium"}, previous_response_id=last_id,input=PLAN_REQUEST, text_format=MigrationPlan,# files, evidence, risks)Propulsé par
Le plan couvrait chaque changement requis et a prévenu qu’un nouvel ID de commande modifierait les métadonnées v2 lors d’une relance. Cet avertissement revient plus tard.
Comment vérifier un plan de migration structuré
Avant d’accorder l’écriture, le harnais vérifie la structure, les preuves et la couverture du plan.
Trois contrôles pour un plan de migration. Image de l’auteur.
Le plan a franchi chaque porte. Il proposait aussi de renommer un paramètre public de client.py pour l’aligner sur l’appellation v2, comme suggéré dans la section nettoyage des specs. Cette proposition devient le test de pilotage.
Comment construire un agent de code GPT-6 Sol avec la Responses API
Un agent de code GPT-6 Sol utilise une boucle d’outils : attendre une réponse, exécuter ses appels de fonctions, et renvoyer les sorties. Notre guide de la Responses API d’OpenAI explique les formats de requête et de résultats d’outils. Cette migration garde la boucle sur une seule connexion WebSocket parce que le pilotage en a besoin.
with client.responses.connect()as conn:
conn.response.create(**base, previous_response_id=plan_id,input=[start_message])for event in conn:if event.type=="response.incomplete":
reason =getattr(event.response.incomplete_details,"reason",None)if reason =="steered":continue# keep reading for the automatic successorraise RuntimeError(reason or"response incomplete")if event.type!="response.completed":continue
calls =[i for i in event.response.output if i.type=="function_call"]ifnot calls:break# GPT-6 Sol says it's done here; the held-out tests decide whether it is
outputs =[{"type":"function_call_output","call_id": c.call_id,"output": tools.run(c.name, c.arguments)}for c in calls]
conn.response.create(**base, previous_response_id=event.response.id,input=outputs)Propulsé par
base garde le modèle, les instructions, les outils et l’effort medium fixes pour la mise en cache du prompt. GPT-6 Sol a exécuté les tests visibles au fil de l’eau, mais il a aussi écrit la plupart des nouveaux tests, ils ne peuvent donc pas servir de contrôle indépendant.
Comment fonctionne le pilotage en cours d’exécution dans GPT-6 Sol ?
Le pilotage en cours d’exécution ajoute une instruction à une réponse encore en cours, sans l’annuler. Après response.created, vous envoyez response.steer sur la même connexion avec l’ID de cette réponse, et le serveur applique l’instruction dans une réponse successeure.
La nouvelle exigence venait de l’équipe storefront : les signatures de CheckoutClient « doivent rester exactement telles qu’elles sont aujourd’hui », car un autre service les appelle. Je ne voulais pas qu’un timer décide du moment, donc le harnais surveille le dépôt. Après chaque lot d’appels d’outils, il compare les signatures publiques sur disque avec les originales, et la première différence arme le pilotage :
if steer_state =="idle"and signature_changes(repo):# CheckoutClient, compared with ast
steer_state ="armed"if event.type=="response.created"and steer_state =="armed":
conn.response.steer(previous_response_id=event.response.id,input=STEER_TEXT)
steer_state ="sent"Propulsé par
Cela garantit que le pilotage tombe après le renommage qu’il contredit, c’est la situation intéressante à tester. Envoyé plus tôt, ce n’est qu’un prompt plus long.
Le serveur a ensuite rapporté le cycle de vie du pilotage :
response.steer.accepted signifie que la mise à jour est en file d’attente, pas encore appliquée
response.incomplete a clos la réponse d’origine avec la raison steered
Une réponse successeure response.created a continué avec la nouvelle exigence
Si la réponse attend un résultat d’outil, le serveur envoie response.steer.pending et retient le pilotage jusqu’à ce que le harnais le renvoie. Continuez à répondre aux appels d’outils pendant qu’un pilotage est en attente.
Qu’est-ce que le pilotage ne change pas ?
Le pilotage change ce que le modèle fait ensuite. Le guide d’OpenAI est clair sur le reste : un pilotage ne réécrit pas la sortie déjà envoyée, n’annule pas les actions antérieures, et ne stoppe pas des outils déjà lancés.
Quand le pilotage est arrivé, le renommage était déjà sur disque dans client.py. GPT-6 Sol l’a annulé, et un contrôle de signatures isolé a confirmé l’interface finale.
Une édition peut être annulée. Un outil qui aurait déjà appelé un système externe ne laisserait rien à annuler ; enregistrez donc l’état du dépôt quand chaque pilotage arrive.
GPT-6 Sol peut-il migrer une codebase Python ?
Dans ce dépôt, oui, mais pas en un seul passage. La première migration respectait son contrat initial, puis la sonde de déploiement a mis au jour un cas manquant.
Qu’ont montré les tests isolés ?
Quand GPT-6 Sol a annoncé la migration terminée, la suite isolée a passé sans tour de réparation. Pour les remboursements, GPT-6 Sol a remplacé l’addition par une lecture cumulative qui ignore aussi les webhooks hors ordre :
- order.refunded_cents += data["amount_refunded"]
+ order.refunded_cents = max(order.refunded_cents, refunded["cents"])Propulsé par
Pour l’idempotence, GPT-6 Sol a conservé un order_id frais à chaque tentative et ajouté un cache de requêtes dans le store de commandes qui répond aux demandes répétées avant qu’elles n’atteignent v2. Ce cache vit en mémoire de processus, ce qui va compter dans un instant.
Les Structured Outputs peuvent-ils être erronés ?
Oui. Le premier rapport a qualifié de régression un test de webhook mis à jour et a omis le risque lié aux relances entre serveurs, alors même que le plan avait nommé ce piège.
Structured Outputs valide le schéma, pas ces affirmations. Recoupez les champs du rapport avec les preuves enregistrées, et ne considérez pas une liste de risques vide comme la preuve qu’il n’en reste aucun.
Qu’ont manqué les tests d’acceptation ?
La suite a manqué une relance routée vers une autre instance d’appli. J’ai ajouté une sonde de déploiement avec deux clients partageant le même processeur de paiement mais pas leur mémoire de processus.
La sonde a échoué. La relance sur la seconde instance a levé payments_adapter_v2.IdempotencyConflict, une exception d’adaptateur que le storefront n’était pas censé voir.
Seul un déploiement multi-processus expose cet échec, qui déclenche l’escalade de raisonnement.
Comment changer l’effort de raisonnement en cours de conversation
Un élément d’entrée configuration_update change l’effort de raisonnement pour la prochaine réponse et toutes les suivantes, jusqu’à une nouvelle mise à jour. L’effort au niveau de la requête reste inchangé, donc le préfixe mis en cache survit. Quand la sonde a échoué, le harnais a envoyé cette requête, suivant le guide de raisonnement :
Les requêtes de migration utilisent store=True, donc après la fermeture du WebSocket le harnais peut poursuivre la chaîne de réponses stockées avec une requête classique à la Responses API.
response = client.responses.create(
model="gpt-6-sol", reasoning={"effort":"medium"},# unchanged, so the prefix survives
instructions=INSTRUCTIONS, tools=TOOLS, tool_choice=allowed(DIAGNOSE_TOOLS),
previous_response_id=last_id,input=[{"type":"configuration_update","reasoning":{"effort":"high"}},{"role":"user","content": probe_failure + DIAGNOSE_FIRST}],)
active_effort ="high"# the harness records it; the response won'tPropulsé par
GPT-6 Sol reçoit l’échec et la topologie de déploiement, sans indication sur le correctif. DIAGNOSE_TOOLS autorise la lecture et les tests, pas l’édition. Conserver les outils et text.format inchangés préserve le préfixe mis en cache.
Un détail d’API est contrariant : response.reasoning.effort renvoie encore le réglage au niveau de la requête après une mise à jour. Le harnais ne peut pas relire l’effort actif dans la réponse ; il enregistre donc lui-même la valeur lorsqu’il envoie la mise à jour et l’étiquette sur toutes les réponses suivantes.
La réparation à l’effort high a-t-elle fonctionné ?
Oui. GPT-6 Sol a remonté l’échec jusqu’au store local du second serveur, puis a suivi le nouvel ID de commande dans les métadonnées de paiement. Le processeur partagé voyait des paramètres différents pour le même request_id.
Le correctif a fait de l’ID de commande une fonction de l’ID de requête, pour que chaque serveur calcule le même :
GPT-6 Sol a aussi ajouté un test visible pour ce cas. La sonde et la suite d’acceptation ont passé, puis un configuration_update a ramené l’effort à medium. Le rapport final a décrit correctement cette fois l’échec réel.
L’application Streamlit du projet rejoue l’exécution enregistrée sans appels API. La vidéo passe de la vue d’ensemble aux événements de pilotage puis aux résultats d’acceptation et de sonde.
Streamlit rejoue la migration et la réparation. Vidéo de l’auteur.
Ce que cela ne montre pas, c’est si medium aurait trouvé la même ligne. Je n’ai exécuté que le chemin avec escalade, donc la preuve est que high a fonctionné ici, pas que c’était nécessaire.
Combien coûte un agent de code GPT-6 Sol ?
Cette exécution enregistrée a coûté 0,7082 $ : 0,7051 $ pour GPT-6 Sol et 0,0031 $ pour GPT-6 Luna. Chaque appel à la Responses API renvoie quatre décomptes de tokens facturables, donc tarifez chaque réponse séparément avec les tarifs évoqués plus haut.
details = usage.input_tokens_details
cached, written = details.cached_tokens, details.cache_write_tokens
ordinary = usage.input_tokens - cached - written # cache writes have their own rate
cost =(
ordinary * PRICE_INPUT
+ cached * PRICE_CACHED_INPUT
+ written * PRICE_CACHE_WRITE
+ usage.output_tokens * PRICE_OUTPUT
)/1_000_000Propulsé par
Sur l’ensemble de l’exécution, 91 % de l’entrée de GPT-6 Sol provenait du cache.
Le plan et le premier rapport ont chacun ajouté un schéma de réponse et n’ont rien lu depuis le cache. Le guide de mise en cache du prompt liste text.format parmi les paramètres qui changent le préfixe. Dans cette exécution, les écritures de cache ont coûté plus que la sortie ; gardez donc instructions et outils fixes, et attendez-vous à ce que les requêtes qui ajoutent un schéma écrivent un nouveau préfixe.
GPT-6 Luna a-t-il fait gagner du travail ?
Pas de manière démontrable. GPT-6 Luna a réduit 56 fichiers à 16, tandis que GPT-6 Sol en a ouvert 16 autres de son côté. Sans référence « sans GPT-6 Luna », je ne peux pas affirmer que la présélection a réduit la lecture totale.
Quand un agent de code doit-il utiliser GPT-6 Sol vs GPT-6 Luna ?
Utilisez GPT-6 Sol là où une erreur coûte cher : planification, édition, lecture des échecs de tests ; et GPT-6 Luna pour des classifications ciblées que vous pouvez vérifier. Dans cette implémentation, GPT-6 Luna a réduit la recherche une fois, et GPT-6 Sol a pris toutes les décisions qui modifiaient des fichiers.
Checklist de déploiement d’un agent de code GPT-6 Sol
Une migration de paiements en production exige des contrôles au-delà de cette expérimentation locale. La plupart résident dans le harnais, pas le modèle :
Exécuter chaque migration dans une branche, un worktree ou un conteneur jetable
Arrêter la boucle à un nombre de tours et un plafond de dépenses fixés
Tester la configuration de déploiement autant que le code : ajouter des contrôles multi-instances à la suite isolée
Retirer secrets et données clients des prompts et journaux d’outils
Exiger une validation humaine du diff final avant fusion
Garder la révision de départ propre disponible pour rollback
Le contrôle multi-instances est celui que cette exécution a appris à la dure. Un contrat de test ne prouve que ce qu’il couvre, et chaque point de la liste limite l’impact quand il couvre moins que prévu.
Conclusion
Northstar a d’abord atteint un contrat valide alors qu’une relance sur un autre serveur cassait encore l’idempotence, un risque nommé par le plan de migration avant toute édition. Une sonde échouée et une réparation ciblée ont produit le résultat que le contrat initial avait manqué.
Je ne garderais l’étape de triage GPT-6 Luna que lorsqu’elle supprime une vraie lecture, je laisserais GPT-6 Sol à medium pour les tours routiniers, et j’augmenterais l’effort quand un contrôle indépendant échoue. Surtout, j’écrirais des contrôles de déploiement dans le contrat avant la première exécution, plutôt qu’après la première surprise.
Je suis ingénieur de données et créateur de communautés. Je travaille sur les pipelines de données, le cloud et les outils d'IA, tout en rédigeant des tutoriels pratiques et percutants pour DataCamp et les développeurs émergents.
FAQ
Le mode WebSocket fonctionne-t-il avec store=false ou Zero Data Retention ?⌄
Oui. La connexion conserve en mémoire l’état des réponses récentes, donc previous_response_id fonctionne avec store=false sur la même connexion. Après une reconnexion, cet état disparaît et la requête renvoie previous_response_not_found.
Que devient un pilotage en file d’attente si la connexion WebSocket tombe ?⌄
Considérez-le comme inconnu. Un pilotage en file d’attente n’existe que sur la connexion en cours, et une connexion dure jusqu’à 60 minutes ; la documentation d’OpenAI indique de ne pas supposer qu’il a survécu. Journalisez chaque pilotage envoyé et comparez-le à l’historique des réponses avant d’en rejouer un.
Puis-je utiliser l’outil intégré apply_patch d’OpenAI avec GPT-6 Sol ?⌄
Oui, la page du modèle GPT-6 Sol liste apply_patch comme pris en charge. Votre application applique toujours chaque patch en local, elle a donc toujours besoin de ses propres contrôles de chemin.
GPT-6 Sol et GPT-6 Luna partagent-ils l’état de conversation ?⌄
Non. L’application passe la présélection GPT-6 Luna dans la requête GPT-6 Sol suivante ; les appels API ne partagent pas l’état automatiquement.
Dois-je envoyer tout le dépôt à GPT-6 Sol au lieu d’utiliser des outils de fichiers ?⌄
Pour un dépôt aussi petit que Northstar, c’est possible. Le piège, c’est qu’un dépôt collé reste dans le contexte de conversation via previous_response_id, donc chaque tour ultérieur retraitera ces tokens, majoritairement comme entrée mise en cache. Une boucle d’outils n’ajoute que les fichiers demandés par GPT-6 Sol et garde chaque édition comme un appel d’outil révisable.
Lancez-vous dans la création d'applications alimentées par l'IA avec l'API OpenAI. Découvrez ce qui fait tourner les applis les plus populaires, comme ChatGPT.
Débloquez des applications d'IA plus avancées, comme la recherche sémantique et les moteurs de recommandation, en utilisant le modèle d'intégration d'OpenAI !
Ici, nous allons utiliser GPT-6 Sol pour migrer Northstar Checkout, un petit service de paiement Python fictif, d’un adaptateur de paiement local v1 vers v2.
Plus précisément, nous verrons comment :
Effectuer un premier appel à l’API GPT-6 Sol et lire ses champs d’usage
Définir le contrat de migration avant que le modèle ne voie le dépôt
Donner à GPT-6 Sol des outils de fichiers et de tests restreints, puis échelonner les accès avec
allowed_toolsUtiliser GPT-6 Luna pour le triage et faire vérifier la présélection par GPT-6 Sol
Renvoyer un plan de migration structuré et le confronter aux fichiers déjà lus par GPT-6 Sol
Lancer la migration via WebSocket et la piloter après le début des éditions
Augmenter l’effort de raisonnement après l’échec d’une sonde de déploiement indépendante
Calculer le coût enregistré à partir de l’usage API
Ce que j’ai appris en chemin
Quatre constats ont changé ma façon d’aborder la prochaine version :
Qu’est-ce que GPT-6 Sol ?
GPT-6 Sol est le niveau intermédiaire de la famille GPT-6 d’OpenAI, et l’ID du modèle dans l’API est
gpt-6-sol. Notre guide des niveaux de modèles GPT-6 couvre le lancement et les benchmarks. Les recommandations GPT-6 d’OpenAI placent GPT-6 Astra en premier, GPT-6 Sol au milieu, et GPT-6 Luna au coût le plus bas.GPT-6 Sol offre une fenêtre de contexte de 1 050 000 tokens et peut renvoyer jusqu’à 128 000 tokens en sortie. L’effort de raisonnement va de
noneàmaxet la valeur par défaut estmedium. Chat Completions ne prend en charge l’appel de fonctions de GPT-6 Sol qu’avecnone, donc toutes les requêtes ici utilisent la Responses API.La tarification et les capacités de l’API déterminent la façon dont le harnais envoie chaque requête.
Combien coûte l’API GPT-6 Sol ?
GPT-6 Sol coûte 2 $ par million de tokens en entrée et 10 $ par million de tokens en sortie pour des requêtes allant jusqu’à 272 000 tokens en entrée, d’après la page de tarification d’OpenAI. L’entrée mise en cache coûte 0,20 $ par million, et l’écriture en cache 2,50 $. Les tarifs de GPT-6 Luna pour ces quatre catégories sont 0,10 $, 0,01 $, 0,125 $ et 0,50 $.
Au-delà de 272 000 tokens en entrée, toute la requête est facturée à 2× les tarifs d’entrée et de cache, et 1,5× le tarif de sortie. Aucune requête de ce projet ne s’en est approchée.
Quelles fonctionnalités de l’API ce tutoriel utilise-t-il ?
Le harnais, c’est-à-dire le code Python autour du modèle, utilise ces contrôles de GPT-6 :
Pilotage en cours d’exécution pour mettre à jour une réponse pendant qu’elle s’exécute
configuration_updatemodifie l’effort de raisonnement sans réécrire le préfixe mis en cacheallowed_toolsdéfinit le sous-ensemble appelable pour une requêteStructured Outputs fixe les champs du plan et du rapport
Ces quatre contrôles restent dans la même chaîne de réponses de la Responses API.
Qu’allons-nous construire avec l’API GPT-6 Sol ?
Nous allons créer un agent qui fait passer Northstar Checkout de Payments Adapter v1 à v2. Les deux adaptateurs sont des remplaçants locaux écrits pour cette expérience, pas de vrais SDK de paiement. Le code complet, les fixtures et l’exécution enregistrée se trouvent dans ce dépôt GitHub.
Le dépôt mêle du code de paiement à des modules sans lien, donc GPT-6 Sol doit trouver lui-même les fichiers concernés. La v2 rompt quatre contrats d’adaptateur :
La création d’un paiement passe de
client.charge(...)àclient.payments.create(...)Les dictionnaires de résultats deviennent des objets typés avec des montants
MoneyLes cartes refusées renvoient un état au lieu de lever une exception
Les webhooks changent de nom, d’enveloppe et d’en-tête de signature
Une recherche/remplacement gère le renommage de méthode. Elle ne gère aucune des évolutions de comportement.
Une boucle de migration, deux modèles GPT-6. Image de l’auteur.
GPT-6 Sol reçoit le cahier des charges, l’arborescence des fichiers et des outils restreints qui deviennent appelables par étapes. Il ne sait ni quels fichiers doivent changer, ni qu’une exigence va évoluer.
Pourquoi cette migration d’API est-elle difficile ?
Deux parties des spécifications sont piégeuses. Ce ne sont pas des bugs plantés ; elles résultent de la rencontre du comportement v2 avec le code existant :
Idempotence. v2 compare les paramètres lorsqu’elle voit un
request_idrépété, mais le checkout place un nouvelorder_iddans les métadonnées à chaque tentative, de sorte qu’une relance naïve est rejetée au lieu d’être dédupliquée.Totaux des remboursements. le webhook
payment.refundedde v2 rapporte le total remboursé à date, tandis que l’ancien gestionnaire additionne chaque valeur avec+=.Les deux passent le contrôle de types. Vous ne les détectez qu’en exécutant l’enchaînement complet du checkout et des remboursements.
Les changements de paiement touchent plusieurs modules Northstar. Image de l’auteur.
La carte sépare les imports directs de l’adaptateur des modules dépendant du comportement de paiement. Ces liens indirects expliquent pourquoi un corrigé couvrant tout le dépôt compte.
Comment testerons-nous la migration ?
Une suite d’acceptation isolée, écrite avant tout appel au modèle, tranche le résultat. GPT-6 Sol ne la voit jamais ; le harnais l’exécute avec pytest sur la copie migrée. Elle vérifie que :
Le checkout réussit via v2, et une relance avec la même clé d’idempotence ne facture qu’une fois
Une carte refusée lève toujours l’erreur publique
CheckoutDeclinedUn remboursement total, deux remboursements partiels et un webhook réémis laissent des totaux corrects
CheckoutClientconserve les mêmes signatures de méthodesAucune référence v1 ne subsiste,
vendor/etMIGRATION.mdsont intacts, et les tests visibles passentLe code d’origine passe déjà les contrôles d’interfaces inchangées et de fichiers protégés ; les autres vérifications mesurent la migration. Un corrigé séparé liste les changements requis, mais seul le harnais le lit.
Les répertoires
acceptance/etprobes/sont hors de la copie du dépôt exposée aux deux modèles. Le corrigé se trouve sousacceptance/, il ne peut donc pas entrer dans l’entrée de GPT-6 Luna, l’arborescence, ni aucun outil du dépôt.La porte de lecture peut renvoyer des chemins issus du propre plan de GPT-6 Sol. La couverture du corrigé est enregistrée à des fins d’évaluation uniquement ; elle ne renvoie jamais à GPT-6 Sol des chemins manquants issus du terrain.
Une sonde de déploiement s’exécute après cette suite. Aucun de ces contrôles n’accepte le message « done » du modèle comme preuve.
Comment configurer l’API GPT-6 Sol en Python
Vous avez besoin de Python 3.10 ou plus récent et d’une clé API avec accès aux deux modèles. Les dépendances incluent l’extra
realtimenécessaire au pilotage :Sur macOS ou Linux, utilisez
source .venv/bin/activateetcp .env.example .env, puis mettezOPENAI_API_KEY=...dans.env.Si votre clé fonctionne déjà avec la Responses API, passez la section suivante.
Effectuez votre premier appel à l’API GPT-6 Sol
La plus petite requête utile confirme la clé, l’ID du modèle et les champs d’usage nécessaires à la section coût :
La réponse indique un effort
medium, etusagecomprendcached_tokensetcache_write_tokens. Laissez de côtétemperatureettop_p. Les deux renvoient un 400 dès lors que l’effort n’est pasnone.Le premier appel GPT-6 Sol renvoie l’usage. Image de l’auteur.
Avec quel effort de raisonnement démarrer ?
Commencez à
medium, la valeur par défaut, et gardez ce réglage au niveau de la requête tout au long de l’exécution. La plupart des tours de migration sont des lectures et de petites éditions. La sonde de déploiement fournit plus tard une raison d’augmenter l’effort.Comment ajouter des outils de dépôt sûrs à un agent de code
La couche d’outils détient les permissions de l’agent. GPT-6 Sol reçoit ces outils-fonctions avec
strict: true:list_filesetsearch_codelocalisent le code pertinentread_filerenvoie un fichier du dépôtedit_filemodifie une occurrence exacterun_testsexécute une cible pytest autoriséeDes schémas stricts vérifient la forme des arguments, pas la sécurité des chemins, donc Python fait respecter la frontière d’écriture :
Le chemin est résolu d’abord, donc
../et les chemins absolus échouent.edit_fileremplace une correspondance exacte, etrun_testsn’accepte que des cibles soustests/.Le harnais renvoie un appel bloqué comme une sortie d’outil
ERROR:, et la boucle continue. Notre guide d’ingénierie de harnais d’agent explique pourquoi ces contrôles doivent vivre dans le harnais plutôt que dans le prompt.Comment tester la frontière des fichiers
Appelez chaque outil avec une entrée qu’il doit rejeter :
Un chemin contenant
..Un chemin absolu
Une écriture sous
vendor/Une cible de test contenant une commande shell
Aucune ne doit passer. Une édition qui correspond à plus d’un emplacement doit demander plus de contexte, et garder les règles dans des fonctions personnalisées les met à un seul endroit testable.
Comment utiliser GPT-6 Luna pour le triage du dépôt
Le triage d’un dépôt est une classification ciblée : évaluer la pertinence de chaque fichier et citer les références v1. GPT-6 Luna reçoit cette tâche et rien d’autre, et s’exécute en premier, avant que GPT-6 Sol n’ait rien cherché.
L’entrée est le cahier des charges plus chaque fichier Python sous
northstar/ettests/. Tout ce qui est notéhighoumediumalimente la présélection que reçoit ensuite GPT-6 Sol.Comment vérifier la présélection de GPT-6 Luna
Comparez la présélection avec le corrigé établi plus tôt, et regardez d’abord le rappel. GPT-6 Luna a conservé tous les fichiers affectés et ajouté quelques fichiers qui n’avaient pas besoin de changements.
GPT-6 Luna réduit de 56 à 16. Image de l’auteur.
Une présélection est une piste, pas une frontière.
Comment utiliser
allowed_toolspour des permissions échelonnéesallowed_toolsest un mode detool_choicequi limite les outils que le modèle peut appeler, tout en gardant la liste complète en place. C’est ainsi que le premier passage de GPT-6 Sol reste en lecture seule : la liste complète est définie à chaque requête, mais seules la liste et la recherche sont appelables.Changer
toolsentre les phases réécrit le préfixe mis en cache. Le guide d’appel de fonctions recommandeallowed_toolslorsque seul le sous-ensemble appelable doit changer.Pourquoi démarrer un agent de code en lecture seule ?
Un passage en lecture seule sépare le diagnostic de l’action. GPT-6 Sol a reçu la présélection de GPT-6 Luna avec un simple avertissement qu’elle pouvait être erronée, et ses recherches d’imports v1, d’appels charge et de noms de webhooks ont, à elles seules, fait remonter tous les fichiers concernés.
Il est aussi allé au-delà de la liste, signalant les modèles de commande, le store de commandes, les sérialiseurs et l’export du grand livre comme dépendances aval à vérifier. Aucun n’a finalement nécessité de changement, mais les lire est la seule façon de le savoir. Je garderais
allowed_toolspour tout agent qui édite des fichiers.Comment utiliser Structured Outputs pour un plan de migration
Le plan de migration est l’endroit où l’agent s’engage sur des fichiers précis avant d’obtenir les droits d’écriture. La planification ajoute
read_file, et le plan revient via Structured Outputs avec les outils coupés :Le plan couvrait chaque changement requis et a prévenu qu’un nouvel ID de commande modifierait les métadonnées v2 lors d’une relance. Cet avertissement revient plus tard.
Comment vérifier un plan de migration structuré
Avant d’accorder l’écriture, le harnais vérifie la structure, les preuves et la couverture du plan.
Trois contrôles pour un plan de migration. Image de l’auteur.
Le plan a franchi chaque porte. Il proposait aussi de renommer un paramètre public de
client.pypour l’aligner sur l’appellation v2, comme suggéré dans la section nettoyage des specs. Cette proposition devient le test de pilotage.Comment construire un agent de code GPT-6 Sol avec la Responses API
Un agent de code GPT-6 Sol utilise une boucle d’outils : attendre une réponse, exécuter ses appels de fonctions, et renvoyer les sorties. Notre guide de la Responses API d’OpenAI explique les formats de requête et de résultats d’outils. Cette migration garde la boucle sur une seule connexion WebSocket parce que le pilotage en a besoin.
basegarde le modèle, les instructions, les outils et l’effortmediumfixes pour la mise en cache du prompt. GPT-6 Sol a exécuté les tests visibles au fil de l’eau, mais il a aussi écrit la plupart des nouveaux tests, ils ne peuvent donc pas servir de contrôle indépendant.Comment fonctionne le pilotage en cours d’exécution dans GPT-6 Sol ?
Le pilotage en cours d’exécution ajoute une instruction à une réponse encore en cours, sans l’annuler. Après
response.created, vous envoyezresponse.steersur la même connexion avec l’ID de cette réponse, et le serveur applique l’instruction dans une réponse successeure.La nouvelle exigence venait de l’équipe storefront : les signatures de
CheckoutClient« doivent rester exactement telles qu’elles sont aujourd’hui », car un autre service les appelle. Je ne voulais pas qu’un timer décide du moment, donc le harnais surveille le dépôt. Après chaque lot d’appels d’outils, il compare les signatures publiques sur disque avec les originales, et la première différence arme le pilotage :Cela garantit que le pilotage tombe après le renommage qu’il contredit, c’est la situation intéressante à tester. Envoyé plus tôt, ce n’est qu’un prompt plus long.
Le serveur a ensuite rapporté le cycle de vie du pilotage :
response.steer.acceptedsignifie que la mise à jour est en file d’attente, pas encore appliquéeresponse.incompletea clos la réponse d’origine avec la raisonsteeredUne réponse successeure
response.createda continué avec la nouvelle exigenceSi la réponse attend un résultat d’outil, le serveur envoie
response.steer.pendinget retient le pilotage jusqu’à ce que le harnais le renvoie. Continuez à répondre aux appels d’outils pendant qu’un pilotage est en attente.Qu’est-ce que le pilotage ne change pas ?
Le pilotage change ce que le modèle fait ensuite. Le guide d’OpenAI est clair sur le reste : un pilotage ne réécrit pas la sortie déjà envoyée, n’annule pas les actions antérieures, et ne stoppe pas des outils déjà lancés.
Quand le pilotage est arrivé, le renommage était déjà sur disque dans
client.py. GPT-6 Sol l’a annulé, et un contrôle de signatures isolé a confirmé l’interface finale.Une édition peut être annulée. Un outil qui aurait déjà appelé un système externe ne laisserait rien à annuler ; enregistrez donc l’état du dépôt quand chaque pilotage arrive.
GPT-6 Sol peut-il migrer une codebase Python ?
Dans ce dépôt, oui, mais pas en un seul passage. La première migration respectait son contrat initial, puis la sonde de déploiement a mis au jour un cas manquant.
Qu’ont montré les tests isolés ?
Quand GPT-6 Sol a annoncé la migration terminée, la suite isolée a passé sans tour de réparation. Pour les remboursements, GPT-6 Sol a remplacé l’addition par une lecture cumulative qui ignore aussi les webhooks hors ordre :
Pour l’idempotence, GPT-6 Sol a conservé un
order_idfrais à chaque tentative et ajouté un cache de requêtes dans le store de commandes qui répond aux demandes répétées avant qu’elles n’atteignent v2. Ce cache vit en mémoire de processus, ce qui va compter dans un instant.Les Structured Outputs peuvent-ils être erronés ?
Oui. Le premier rapport a qualifié de régression un test de webhook mis à jour et a omis le risque lié aux relances entre serveurs, alors même que le plan avait nommé ce piège.
Structured Outputs valide le schéma, pas ces affirmations. Recoupez les champs du rapport avec les preuves enregistrées, et ne considérez pas une liste de risques vide comme la preuve qu’il n’en reste aucun.
Qu’ont manqué les tests d’acceptation ?
La suite a manqué une relance routée vers une autre instance d’appli. J’ai ajouté une sonde de déploiement avec deux clients partageant le même processeur de paiement mais pas leur mémoire de processus.
La sonde a échoué. La relance sur la seconde instance a levé
payments_adapter_v2.IdempotencyConflict, une exception d’adaptateur que le storefront n’était pas censé voir.Seul un déploiement multi-processus expose cet échec, qui déclenche l’escalade de raisonnement.
Comment changer l’effort de raisonnement en cours de conversation
Un élément d’entrée
configuration_updatechange l’effort de raisonnement pour la prochaine réponse et toutes les suivantes, jusqu’à une nouvelle mise à jour. L’effort au niveau de la requête reste inchangé, donc le préfixe mis en cache survit. Quand la sonde a échoué, le harnais a envoyé cette requête, suivant le guide de raisonnement :Les requêtes de migration utilisent
store=True, donc après la fermeture du WebSocket le harnais peut poursuivre la chaîne de réponses stockées avec une requête classique à la Responses API.GPT-6 Sol reçoit l’échec et la topologie de déploiement, sans indication sur le correctif.
DIAGNOSE_TOOLSautorise la lecture et les tests, pas l’édition. Conserver les outils ettext.formatinchangés préserve le préfixe mis en cache.Un détail d’API est contrariant :
response.reasoning.effortrenvoie encore le réglage au niveau de la requête après une mise à jour. Le harnais ne peut pas relire l’effort actif dans la réponse ; il enregistre donc lui-même la valeur lorsqu’il envoie la mise à jour et l’étiquette sur toutes les réponses suivantes.La réparation à l’effort
higha-t-elle fonctionné ?Oui. GPT-6 Sol a remonté l’échec jusqu’au store local du second serveur, puis a suivi le nouvel ID de commande dans les métadonnées de paiement. Le processeur partagé voyait des paramètres différents pour le même
request_id.Le correctif a fait de l’ID de commande une fonction de l’ID de requête, pour que chaque serveur calcule le même :
GPT-6 Sol a aussi ajouté un test visible pour ce cas. La sonde et la suite d’acceptation ont passé, puis un
configuration_updatea ramené l’effort àmedium. Le rapport final a décrit correctement cette fois l’échec réel.L’application Streamlit du projet rejoue l’exécution enregistrée sans appels API. La vidéo passe de la vue d’ensemble aux événements de pilotage puis aux résultats d’acceptation et de sonde.