OpenClaw 3.13 → 3.28 : rapport de migration
Trois pièges, un crash loop TTS, et pourquoi Docker m'a protégé d'un bug npm que je n'avais pas vu venir. Migration directe sur Neog.
Partie 9 de la série OpenClaw — Migration complète de Neog de la 3.13 à la 3.28.
Le 29 mars, j’ouvre le Control UI d’OpenClaw pour lancer la migration que je repoussais depuis deux semaines. J’étais sur la 3.13. Ma cible : la 3.24 — la release qui avait introduit le breaking change TTS, ClawHub, et les providers de recherche natifs. J’avais lu les changelogs. J’avais un plan.
La bannière affichait : “Update available: v2026.3.28.”
Quatre releases en quatre jours. On a requalifié avant de toucher quoi que ce soit.
Ce n’est pas un résumé de changelog. C’est ce qui s’est passé réellement quand on essaie de combler 15 versions sur un agent qui tourne en Docker sur une VM Ubuntu — les pièges, les workarounds, ce que openclaw doctor --fix était censé gérer et n’a pas géré, et les trois décisions que j’ai consciemment choisies de ne pas prendre.
Le chemin d’upgrade : 3.13 → 3.28, sans étapes intermédiaires
Première bonne nouvelle : le saut est direct. Pas besoin de passer par la 3.22, puis la 3.24, puis la 3.28. Un pull, un relancement.
docker compose pull
docker compose up -d
C’est le principe. En pratique, ces deux commandes cachaient deux pièges dans lesquels je suis tombé tête la première.
Piège #1 : docker compose restart ne fait pas ce qu’on croit
J’ai pull la 3.28. Confirmé que l’image était là. Puis j’ai lancé :
docker compose restart
Les containers sont remontés. J’ai vérifié la version :
docker exec neog-gateway openclaw --version
# OpenClaw 2026.3.13
Toujours la 3.13. J’ai re-pull, en pensant que ça n’avait pas fonctionné. Même résultat.
Comportement Docker classique que je connaissais intellectuellement mais que je n’avais jamais subi concrètement : restart redémarre le process dans le container existant. Il ne recrée pas le container depuis la nouvelle image. Pour ça, il faut up -d, qui détruit et reconstruit.
docker compose up -d
# OpenClaw 2026.3.28
Évident après coup. Le genre de chose qui coûte 20 minutes quand on est en pleine migration et que le gateway continue de retourner la mauvaise version.
Leçon intégrée dans restore-openclaw-config.py : toujours up -d, jamais restart pour une upgrade.
Piège #2 : Le breaking change TTS et pourquoi doctor --fix l’a raté
La release 3.22 a introduit un breaking change dans la config TTS :
tts.openai → tts.providers.openai
openclaw doctor --fix est censé gérer ce type de migration automatiquement. Il ne l’a pas fait — et la raison est un problème de timing facile à rater.
J’avais lancé doctor --fix avant de puller la nouvelle image, comme vérification pré-migration sur mon setup 3.13. L’outil a tourné contre l’image 3.13, n’a rien trouvé à migrer (parce que rien n’était cassé sur la 3.13), et est sorti proprement.
Ensuite j’ai pull la 3.28, lancé avec up -d, et le gateway est immédiatement parti en crash loop :
messages.tts: Unrecognized key: "openai"
messages.tts: Unrecognized key: "openai"
messages.tts: Unrecognized key: "openai"
La config parfaitement valide sur la 3.13 était maintenant invalide sur la 3.28. Et doctor --fix sur la nouvelle image ne pouvait pas tourner parce que le gateway devait être up d’abord — et le gateway crashait à cause de la mauvaise config. Un catch-22.
Le fix : arrêter tous les containers, éditer le JSON directement sur le filesystem de la VM pendant que tout est éteint, puis relancer.
docker compose down
# éditer openclaw.json sur la VM :
# "tts": { "openai": { ... } }
# devient :
# "tts": { "providers": { "openai": { ... } } }
docker compose up -d
Le gateway est remonté proprement. Ensuite doctor --fix a tourné normalement — sur une instance saine, comme il est conçu pour le faire.
La leçon dans restore-openclaw-config.py : doctor --fix doit tourner après que la nouvelle image est up, pas avant. On a mis à jour le script pour imposer cet ordre.
Piège #3 : Le profil CLI est inutilisable quand le gateway est down
OpenClaw embarque un profil openclaw-cli dans Docker Compose spécifiquement pour lancer des commandes CLI quand le gateway a des problèmes. Bonne idée en théorie. Le profil utilise :
network_mode: "service:openclaw-gateway"
Ce qui signifie que le container CLI partage le namespace réseau du gateway. Si le gateway est down, le container CLI n’a pas de réseau. Si le gateway est en crash loop, on ne peut pas s’y attacher.
Dans la situation de crash loop TTS décrite plus haut, openclaw-cli était totalement inutilisable. Le container démarrait et perdait immédiatement la connectivité.
Workaround : Python directement sur le filesystem de la VM. Pas élégant, mais ça marche, et ça ne nécessite aucun container sain :
# Sur la VM, tous containers arrêtés
python3 restore-openclaw-config.py --dry-run
# inspecter la sortie, puis :
python3 restore-openclaw-config.py --apply
C’est pour ça que restore-openclaw-config.py existe. Il était déjà dans le stack pour exactement ce scénario. La migration a validé qu’il fonctionne sous conditions de stress réelles.
Le bug npm que je n’ai pas subi (et pourquoi Docker en est la raison)
La release 3.22 embarquait un bug de packaging dans la distribution npm qui a cassé le Dashboard et l’intégration WhatsApp pour les utilisateurs installés via npm install -g openclaw. Le problème a été corrigé en 3.22.1, mais pas avant une vague de remontées dans la communauté.
Je n’ai rien subi. Pas parce que j’ai été prudent, mais parce que je ne suis pas sur npm. Neog tourne entièrement en Docker. Mon docker compose pull a récupéré l’image corrigée, et il n’y avait rien à déboguer.
C’est l’argument récurrent pour Docker plutôt que npm sur tout ce qui tourne en continu : on est isolé des problèmes de packaging au niveau de l’hôte, et on peut revenir à une image précédente en quelques secondes si quelque chose cloche. Je le savais en théorie. La 3.22 l’a rendu concret.
ClawHub : j’ai regardé, j’ai pas touché
L’une des fonctionnalités phares des releases récentes d’OpenClaw est ClawHub — un registry centralisé pour les skills et plugins, maintenant le défaut en remplacement de npm pour la gestion des plugins. La sortie du doctor l’a signalé immédiatement :
✓ 7 skills éligibles pour la synchronisation ClawHub
⚠ 45 skills avec des requirements non résolus (intégrations manquantes probables)
J’ai fermé cette section et je suis passé à la suite.
Mes skills sont installés manuellement dans ~/.openclaw/workspace/skills/. Ça marche. Les 45 avec des requirements manquants sont presque certainement des skills communautaires qui attendent des intégrations que je n’ai pas configurées. Ils ne sont pas cassés, ils sont juste hors scope.
ClawHub, c’est le prochain article. Pas celui-là. Transformer une session de migration en évaluation de ClawHub aurait été une erreur — trop de variables en mouvement en même temps. Neog est un agent de production. Je n’introduis pas plusieurs changements simultanément.
SearXNG vs providers natifs : j’ai pas bougé, et voilà pourquoi
OpenClaw 3.24+ embarque une intégration native pour Exa, Tavily, Firecrawl, et x_search de xAI. Des vrais providers de recherche sémantique, câblés nativement dans la couche d’outils OpenClaw. Sans workaround bash requis.
Mon setup actuel a tools.web.search.enabled = false dans openclaw.json. L’agent utilise SearXNG via bash+curl, un container Docker sur le réseau interne neog-net, zéro trafic externe. Le paramètre a survécu à toute la migration sans être touché.
| SearXNG (actuel) | Exa | Tavily | |
|---|---|---|---|
| Coût | 0€ | Payant (free tier) | Payant |
| Clé API | Aucune | Obligatoire | Obligatoire |
| Vie privée | 100% local | Données sortantes | Données sortantes |
| Débit | Illimité | Rate-limited | Rate-limited |
Le seul argument réel pour basculer serait la qualité des résultats — Exa en particulier fait de la recherche sémantique que SearXNG ne fait pas. Mais ça implique de payer une clé API, d’accepter des limites de débit, et de router mes requêtes de recherche vers des serveurs externes.
Je n’ai pas ce signal en ce moment — SearXNG tourne, l’agent s’en sert, ça passe. Verdict honnête : j’ai regardé les providers natifs, compris ce qu’ils offrent, et j’ai fait un choix délibéré de garder mon setup. Ce n’est pas la même chose qu’ignorer la feature.
Ce que la migration a durci dans restore-openclaw-config.py
Avant cette migration, le script gérait l’essentiel : restaurer openclaw.json depuis une sauvegarde, relancer le stack, vérifier que le gateway montait. Après cette migration, il fait plus :
- Impose
up -dplutôt querestartpour toute opération d’upgrade — vérifie si le tag de l’image a changé et force une recréation complète si c’est le cas. - Valide la structure de la config TTS avant d’écrire sur le disque — si la clé ne correspond pas au schéma attendu pour la version détectée, il flag le mismatch avant que le gateway démarre.
- Reporte
doctor --fixau post-lancement — attend un statut gateway sain avant de lancer la passe de fix.
Ce ne sont pas des améliorations théoriques. Ce sont le résultat direct de trois échecs concrets pendant la migration. Le script encode maintenant ces leçons.
État de Neog sur la 3.28
L’agent tourne. La migration a pris une session, un crash loop, et trois leçons qui sont maintenant dans la documentation et le script de restore.
Ce que je n’ai pas fait : migrer vers ClawHub, basculer sur les providers de recherche natifs, ni toucher quoi que ce soit qui fonctionnait.
Ce que j’ai fait : migrer proprement de la 3.13 à la 3.28, durcir le script de restore, et documenter exactement ce qui a cassé et pourquoi.
La suite : ClawHub. Cette évaluation mérite sa propre session, sans migration en parallèle. 7 skills éligibles, 45 avec des requirements manquants — il y a une vraie question sur si le workflow ClawHub s’adapte à la façon dont Neog est construit.
La commande de mise à jour dans le bon ordre :
docker compose pull && docker compose up -d && \
docker exec neog-gateway openclaw doctor --fix
up -d d’abord. doctor --fix ensuite. Pas l’inverse.
Partager cet article