Chaque timeout de votre stack suppose un client qui finit par abandonner. Un onglet de navigateur se ferme. Une tâche CI atteint son heure limite. Un humain s'éloigne. Les valeurs par défaut héritées de votre load balancer, de votre gateway et de votre bibliothèque HTTP ont été calibrées pour un appelant dont la patience se mesure en secondes.
Anthropic affirme que Claude Opus 5.5 reste sur une tâche pendant 18 heures ou plus.
Ce n'est pas une affirmation sur une seule requête HTTP très longue. C'est une affirmation sur la cohérence : le modèle travaille sur un objectif unique au cours d'une session bien plus longue que tout ce que votre API a servi. Quand l'une de ces sessions pointe vers vos endpoints, elle survit à vos jetons d'accès, à votre fenêtre d'idempotence, à votre cycle de déploiement et à la plupart de vos budgets de nouvelle tentative. Et contrairement à un humain, elle ne remarquera pas qu'elle devrait s'arrêter.
C'est un problème de conception d'API, pas un problème de modèle. Voici ce qui casse, et ce qu'il faut changer.
Ce qu'Anthropic a réellement publié
Les chiffres du fournisseur pour le nouveau modèle, afin que nous raisonnions à partir de la même fiche :
| Propriété | Claude Opus 5.5 |
|---|---|
| Identifiant du modèle API | claude-opus-5-5 |
| Entrée / sortie | 4 $ / 20 $ par million de tokens |
| Lecture d'entrée mise en cache | 0,20 $ par million (écriture de cache 5 $) |
| Fenêtre de contexte | 1 M |
| Sortie maximale | 128 k |
| Mode rapide | 8 $ / 40 $ par million |
| Coût d'exécution vs Opus 5 | 40 % de moins |
| Vitesse de sortie vs Opus 5 | 30 % plus rapide |
| Durée de maintien sur tâche | 18 h et plus |
| Disponibilité | Claude Platform, AWS, GCP, Azure |
Benchmarks issus de la même annonce : Terminal-Bench 4.0 66,4 %, OSWorld 2.0 81,8 %, AutomationBench 40,0 %, FrontierCode v1.1 54,4 %, CursorBench 4.0 57,8 %, Humanity's Last Exam 67,7 % avec outils, Chartography 89,0 %, GDPval-AA v2.1 à 1846 Elo, et 85 % de tentatives réussies de contournement de frontières en moins.
Le chiffre de 18 heures est celui qui atterrit sur votre infrastructure. Les scores de benchmark changent le modèle que vous choisissez. La durée de maintien change ce que votre API doit survivre.
Six hypothèses qui cessent de tenir
| Hypothèse | Pourquoi elle tenait auparavant | Ce qu'un agent de 18 heures lui fait |
|---|---|---|
| Un appel se termine ou échoue dans un seul timeout | Les appelants étaient interactifs | Le travail est plus long que n'importe quel timeout d'inactivité que vous pouvez définir sans risque |
| Réessayer est bon marché car la fenêtre est courte | Les doublons arrivaient à quelques secondes d'intervalle | Les doublons arrivent à quelques heures d'intervalle, après la fermeture de votre fenêtre de déduplication |
| Le justificatif d'authentification valide au début l'est encore à la fin | Les sessions étaient plus courtes que le TTL du jeton | Les jetons tournent deux ou trois fois au cours d'une même tâche |
| Un flux est une connexion | Les flux duraient le temps d'une réponse | La connexion tombera, et le travail n'est pas terminé |
| Le client se souvient de ce qu'il faisait | L'état vivait dans un seul processus | L'agent compacte son contexte, redémarre, et a besoin que vous le lui rappeliez |
| Le client peut dire qu'il progresse | Un humain regardait un indicateur de chargement | Sans progression, l'agent soit redémarre la tâche, soit attend indéfiniment |
Chacune a une correction ennuyeuse, bien comprise, et généralement ignorée parce que rien ne forçait la question. Quelque chose la force maintenant.
Renvoyer des identifiants, pas du travail
Le changement à plus forte valeur : toute opération susceptible de dépasser quelques secondes renvoie immédiatement une ressource de tâche au lieu de maintenir la connexion.
POST /v1/reports HTTP/1.1
Host: api.example.com
Idempotency-Key: 01J9Z4KCQ7M3XN2YB8V6H0
Content-Type: application/json
{"dataset": "orders_2026_q3", "format": "parquet"}
HTTP/1.1 202 Accepted
Location: /v1/jobs/job_01J9Z4KD
Retry-After: 5
Content-Type: application/json
{
"id": "job_01J9Z4KD",
"status": "queued",
"created_at": "2026-09-23T04:12:09Z",
"api_version": "2026-08-01"
}
Ensuite, la ressource de statut porte tout ce dont l'agent a besoin pour décider quoi faire ensuite :
{
"id": "job_01J9Z4KD",
"status": "running",
"progress": { "completed": 41200, "total": 180000, "unit": "rows" },
"started_at": "2026-09-23T04:12:11Z",
"updated_at": "2026-09-23T05:47:02Z",
"expires_at": "2026-09-24T04:12:09Z",
"retry_after_seconds": 15,
"result_url": null,
"error": null
}
Quatre champs font le vrai travail. progress avec une unit explicite permet au modèle de raisonner sur le caractère rationnel d'attendre, plutôt que de deviner à partir du temps écoulé. retry_after_seconds place la cadence d'interrogation sous le contrôle du serveur, ce qui compte quand l'appelant n'a aucun instinct de politesse. expires_at indique à l'agent combien de temps l'identifiant reste valable, afin qu'il puisse faire un point de sauvegarde avant de le perdre. api_version épingle la tâche au contrat sous lequel elle a été créée, la seule chose qui se dresse entre votre déploiement de 15 h et une exécution lancée à l'aube.
Les webhooks sont le meilleur signal d'achèvement lorsque vous pouvez les proposer, et l'interrogation est la solution de repli quand l'agent n'a pas d'adresse appelable. Notre analyse interrogation versus webhooks pour les appels d'agent de longue durée couvre ce compromis. Ce qui change à un horizon de 18 heures, c'est qu'il vous faut les deux, car un webhook livré à la troisième heure à un agent qui a depuis compacté son contexte atteint un appelant qui ne se souvient plus d'avoir demandé.
Faire survivre l'idempotence à la tâche
La plupart des implémentations d'idempotence stockent la clé pendant un jour ou moins, et cela suffisait toujours. Un agent qui réessaie un appel de provisionnement échoué tard dans une longue exécution tombe en dehors de la fenêtre de déduplication d'origine, et à ce moment votre API refait joyeusement le travail deux fois.
Trois changements coûtent très peu :
- Publiez la fenêtre. Renvoyez l'expiration dans la réponse pour que l'appelant puisse raisonner dessus, au lieu de la documenter une fois en espérant que cela suffise.
- Dites quand vous avez rejoué. Un en-tête
Idempotency-Replayed: truetransforme un no-op silencieux en quelque chose sur quoi l'agent peut agir. - Rejetez bruyamment les incohérences. Même clé, corps différent signifie que l'appelant a perdu la trace de son propre état. Renvoyez
409avec l'empreinte de la requête d'origine au lieu de servir un résultat obsolète.
HTTP/1.1 200 OK
Idempotency-Replayed: true
Idempotency-Expires: 2026-09-24T04:12:09Z
Lorsque l'opération est réellement dangereuse, préférez une clé naturelle fournie par le client à une clé opaque. Un transfer_id dérivé du fait métier survit à la compaction de la mémoire d'un agent d'une manière qu'un UUID aléatoire qu'il a généré il y a onze heures ne fait pas. Notre introduction à l'idempotence pour agents détaille les modes de défaillance.
Supposez que le justificatif d'authentification expire en cours de tâche
Une exécution de 18 heures survit à presque tous les jetons d'accès de courte durée. C'est la bonne posture de sécurité, mais uniquement si votre API rend la distinction lisible.
Renvoyez 401 avec un défi WWW-Authenticate: Bearer error="invalid_token" lorsque le jeton a expiré, et réservez 403 à un principal qui n'a pas la permission. Les agents traitent ces cas très différemment : l'un signifie rafraîchir et continuer, l'autre signifie arrêter et signaler. Les confondre en une défaillance générique est la façon d'obtenir un agent qui brûle quatre heures à réessayer quelque chose qu'il ne sera jamais autorisé à faire.
Liez les tâches au principal, pas à l'instance de jeton. Une tâche démarrée sous un jeton qui a depuis tourné doit rester lisible par la même identité, sinon chaque rafraîchissement de justificatif d'authentification orpheline le travail en cours.
Traitez un flux comme reprenable, pas comme une connexion
Les flux longs tombent. Supposez-le, et concevez la reconnexion plutôt que la connexion.
Pour les événements envoyés par le serveur, cela signifie donner à chaque événement un id monotone, honorer l'en-tête de requête Last-Event-ID à la reconnexion, et émettre un commentaire keepalive à un intervalle plus court que le timeout d'inactivité le plus serré entre vous et le client. Nommez les clés de configuration dans vos propres documents, car le lecteur doit aller les modifier : idle_timeout.timeout_seconds sur un load balancer AWS, proxy_read_timeout dans nginx, timeout sur un service Cloud Run. Le point n'est pas une valeur spécifique. C'est que la valeur existe, qu'elle est plus courte que le travail, et que personne ne l'a examinée depuis la création du service. Notre guide du streaming SSE couvre le format de transmission ; la partie spécifique aux agents est la reprise.
Les en-têtes de limitation de débit comptent plus que d'habitude aussi. RateLimit-Limit, RateLimit-Remaining et RateLimit-Reset permettent à un modèle de rythmer sa propre cadence sur une longue exécution, et un Retry-After sur chaque 429 élimine les conjectures. Un agent à qui l'on donne un nombre le respecte. Un agent à qui l'on ne donne rien invente un backoff, et son invention ne sera pas meilleure que la vôtre.
Le volet coût est une décision de conception
Regardez à nouveau la ligne des tarifs. L'entrée coûte 4 $ par million de tokens et une lecture en cache coûte 0,20 $, une différence d'un facteur vingt sur la partie de la charge utile qu'un agent renvoie le plus souvent, et sur une fenêtre de contexte de 1 M les chiffres absolus grossissent vite. Les écritures de cache à 5 $ signifient que la première passe coûte légèrement plus qu'une lecture simple, donc la mise en cache ne paie que lorsque le préfixe est réellement réutilisé. Sur dix-huit heures, il l'est.
C'est ici que votre surface d'API devient une entrée de coût sur la facture de quelqu'un d'autre. Si votre spécification OpenAPI, vos définitions d'outils ou votre catalogue d'erreurs se trouvent au début du contexte d'un agent, la stabilité des octets est une fonctionnalité. Sérialisez de manière déterministe. Gardez l'ordre des clés stable. Versionnez les définitions d'outils au lieu de les modifier sur place. Une réorganisation cosmétique de votre spécification invalide un préfixe mis en cache et refacture le tout au prix d'entrée plein, et le client qui paie cela ne saura jamais que c'était vous.
L'échelle n'est pas hypothétique. OpenAI a divulgué que son chercheur médian dépense plus de 600 $ par jour en agents de codage, le 90e centile dépassant 7 000 $ par jour. Voilà ce que coûte le travail agentique continu quand personne ne l'optimise, et une partie de la raison pour laquelle trois lancements de modèles en deux jours mettaient tous en avant le coût par tâche plutôt que le coût par token. L'arithmétique du moment où la mise en cache est rentable se trouve dans notre décomposition des coûts de mise en cache d'Opus 5.5.
Testez le chemin long avant qu'un agent ne le découvre
Rien de tout cela n'est vérifiable en cliquant une fois sur envoyer et en lisant un 200. Les défaillances vivent à la neuvième heure.
Dans Apidog, modélisez l'ensemble du cycle de vie comme un scénario de test plutôt qu'une seule requête : vérifiez que l'appel de création renvoie 202 avec un Location et un Retry-After, bouclez sur l'endpoint de statut jusqu'à un état terminal, et vérifiez que progress.completed ne recule jamais. Cette dernière assertion attrape plus de vrais bugs que n'importe quelle vérification de code de statut, car une progression non monotone est ce qui convainc un agent de tout reprendre.
Ensuite, cassez-le délibérément avec un serveur mock. Servez une tâche qui reste running pendant vingt interrogations puis échoue. Servez un 429 sans Retry-After et observez ce que fait votre client. Servez un 401 à mi-parcours pour confirmer que le chemin de rafraîchissement fonctionne pendant qu'une tâche est en cours. Le test SSE d'Apidog maintient une connexion de streaming ouverte et fait des assertions sur des événements individuels, la seule façon pratique de vérifier que la reprise par Last-Event-ID renvoie le bon curseur au lieu de rejouer depuis zéro. Câblez le scénario dans la CI pour qu'un futur changement de timeout fasse échouer un test au lieu de l'exécution nocturne d'un client. Apidog est gratuit pour commencer, et le scénario que vous construisez une fois couvre tous les endpoints de longue durée que vous possédez.
La courte liste de vérification
- Les opérations longues renvoient
202avec un identifiant de tâche, jamais une connexion maintenue - Les réponses de statut portent la progression, une unité, un intervalle d'interrogation choisi par le serveur et une expiration
- Les tâches épinglent la version d'API avec laquelle elles ont été créées
- Les fenêtres d'idempotence sont publiées, les rejeux sont étiquetés, la réutilisation d'une clé avec un corps modifié renvoie
409 401pour les jetons expirés est distinguable de403pour les jetons refusés- Les tâches appartiennent à un principal, pas à une instance de jeton
- Les flux portent des identifiants d'événement, honorent
Last-Event-ID, et envoient des keepalives dans le timeout d'inactivité le plus court du chemin - Chaque
429porte unRetry-After, et les en-têtes de limitation de débit sont toujours présents - La spécification et les définitions d'outils se sérialisent de manière stable au niveau des octets pour que les caches côté client restent chauds
Opus 5.5 n'a inventé aucune de ces exigences. Il a supprimé la dernière excuse pour les ignorer, car le client qui abandonnait autrefois avant de trouver les failles les traverse désormais sans interruption pendant dix-huit heures.
