Passer à Claude Sonnet 5.5 : les trois choses qui cassent
Sonnet 5.5 est 30 % plus rapide que Sonnet 5, au même prix par token. Changer le nom du modèle est facile ; trois habitudes du code, moins.
Chaque montée de version commence par le même petit mensonge qu’on se raconte : ce n’est qu’une chaîne de caractères. On ouvre la config, on remplace un nom de modèle par un autre, on déploie, et on part se faire un café. Avec Claude Sonnet 5.5, ce mensonge tient une dizaine de minutes, le temps que la première requête revienne sous une forme que le code n’attendait pas, ou ne revienne pas du tout.
La migration en vaut pourtant la peine. D’après Anthropic, Sonnet 5.5 est plus intelligent et plus efficace que Sonnet 5, 30 % plus rapide, et le prix par token ne bouge pas. Comme il lui faut en général moins de tokens pour le même travail, l’annonce parle d’un coût jusqu’à 30 % plus bas pour la plupart des usages. La question n’est donc pas s’il faut migrer, mais quoi corriger en chemin. J’en avais fait une fiche courte sur Consonance ; voici la version longue, avec le code.
L’idée en une phrase
Changez le nom du modèle, puis corrigez les trois endroits où Sonnet 5.5 ne tolère plus les vieilles habitudes : la lecture du premier bloc, la réflexion coupée et l’outil forcé.
model="claude-sonnet-5-5"
1. Votre code lit content[0].text
C’est le piège silencieux, parce que l’API ne renvoie aucune erreur. Sonnet 5.5 réfléchit par défaut : une requête sans champ thinking tourne en réflexion adaptative. La réponse peut donc commencer par un bloc thinking, et la ligne qui récupère le texte du premier bloc plante, ou vous rend autre chose que ce que vous croyez.
La correction consiste à ne plus présumer de la position et à lire chaque bloc selon son type. Voici la requête qu’Anthropic donne comme fonctionnelle telle quelle sur Sonnet 5.5 :
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Analyze the trade-offs between microservices and monolithic architectures",
}
],
output_config={"effort": "medium"},
)
for block in response.content:
if block.type == "text":
print(block.text)
Toute la leçon tient dans la boucle finale, et plus précisément dans une ligne :
if block.type == "text":
Le guide de migration ajoute deux réflexes à prendre au passage. Dans les boucles d’appels d’outils, renvoyez les blocs thinking tels quels, y compris les vides. Et revoyez max_tokens : il couvre la réflexion plus le texte, et les tokens de réflexion sont facturés comme des tokens de sortie.
2. Vous envoyiez thinking={"type": "disabled"}
Si vous faisiez tourner Sonnet 5 sans réflexion, ce réglage précis renvoie désormais une erreur 400 invalid_request_error. Il est remplacé par une nouvelle valeur, between_tools. Avec elle, le modèle ne réfléchit pas avant de répondre : la réflexion n’a lieu qu’entre les appels d’outils, et Anthropic indique que le temps de réponse total est identique ou plus court. Voici l’avant/après tiré de l’annonce :
# Before: Claude Sonnet 5
client.messages.create(
model="claude-sonnet-5",
max_tokens=16000,
thinking={"type": "disabled"},
output_config={"effort": "xhigh"},
messages=[{"role": "user", "content": "..."}],
)
# After: Claude Sonnet 5.5
client.messages.create(
model="claude-sonnet-5-5",
max_tokens=16000,
thinking={"type": "between_tools"},
output_config={"effort": "high"},
messages=[{"role": "user", "content": "..."}],
)
Regardez bien : l’effort passe aussi de xhigh à high. Ce n’est pas un détail, car between_tools a ses règles :
- Il fonctionne en effort
low,mediumethigh. Enxhighoumax, il renvoie une erreur 400 ; pour monter jusque-là, utilisez la réflexion adaptative. - Il n’accepte aucun autre champ. Envoyer
display,budget_tokensoublock_bindingavec lui renvoie une erreur 400. - L’effort ne peut pas changer en cours de conversation. Pour un niveau différent à chaque tour, passez par la réflexion adaptative.
- Les courtes mises à jour que le modèle écrit entre deux appels d’outils arrivent toujours sous forme de blocs
thinking. Retour direct à la section 1. - Aucun en-tête bêta n’est nécessaire, mais si votre version du SDK ne connaît pas
between_tools, mettez-la à jour.
Dernière nuance : pour une requête sans outils qui demande quand même quelques étapes de raisonnement, l’annonce recommande la réflexion adaptative plutôt que between_tools.
3. Vous forciez un outil avec tool_choice
Un tool_choice de type any ou tool est refusé avec une erreur 400, y compris sur l’endpoint de comptage de tokens. Le message ne laisse aucun doute :
tool_choice: type "tool" and "any" are not supported for this model.
Le remplacement se fait en trois temps. Envoyez tool_choice={"type": "auto"}. Marquez l’outil "strict": True pour que son entrée respecte le schéma. Et comme auto laisse le modèle libre de répondre sans appeler l’outil, dites dans le prompt quand l’utiliser :
weather_tool = {
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
"additionalProperties": False,
},
"strict": True,
}
client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
tools=[weather_tool],
tool_choice={"type": "auto"}, # was {"type": "tool", "name": "get_weather"}
messages=[
{"role": "user", "content": "What's the weather in Paris? Use the get_weather tool."}
],
)
Le mode strict exige additionalProperties: false sur chaque objet du schéma, pas seulement à la racine. C’est le détail qui coince dès que l’entrée contient des objets imbriqués.
Laisser Claude Code faire la partie ingrate
Dans un vrai projet, ces motifs sont dispersés dans des dizaines de fichiers. Claude Code peut mener la migration à votre place via le skill Claude API intégré, qui applique le changement d’identifiant et les paramètres cassants dans toute la base de code :
/claude-api migrate this project to claude-sonnet-5-5
Même ainsi, certains points relèvent du jugement plutôt que du rechercher-remplacer :
- Les niveaux d’effort sont recalibrés. Un niveau ne produit plus la même quantité de réflexion que sur Sonnet 5 : votre ancien réglage ne se transpose pas. Refaites vos tests d’effort. Par défaut, c’est
highsur l’API Claude etmediumdans Claude Code. - Les grandes images coûtent plus cher. Une image 2000×1500 coûte environ 2,5 fois plus de tokens qu’avec Sonnet 4.6. Si le détail ne sert à rien, réduisez-la avant l’envoi.
- La liste complète est plus longue. Le guide compte cinq changements cassants et un changement de forme de la réponse. Au-delà de ceux vus ici, vérifiez les conversations en ajout seul, le computer use et l’outil advisor si vous les utilisez.
Pour conclure
Le nom du modèle, c’est la partie facile. La vraie migration tient en trois petits changements dans la façon dont votre code parle au modèle : lire les blocs selon leur type, remplacer disabled par between_tools, et troquer l’outil forcé contre auto, un schéma strict et un prompt explicite. Faites-les, refaites vos tests d’effort, et vous obtenez un modèle plus rapide au même prix par token, sans erreur 400 surprise en production.