En bâtissant une démo de réservation de voyage agentique, j'ai trouvé que le remède aux voyageurs plantés n'est pas un meilleur modèle mais une machine à états déterministe avec un rollback Saga.
Agentic AITravel TechnologyAI Agents

Mon agent de réservation a dit à un voyageur « tout est bon » sans hôtel. J'ai cessé de faire confiance au LLM pour piloter le flux.

Ashutosh SinghalAshutosh Singhal1 juillet 202612 min

La nuit où mon agent a dit à un voyageur qu'il avait réservé une chambre qui n'existait pas

Je regardais un prototype tourner quand c'est arrivé. Mon premier agent de réservation de voyage, une conception LLM-dans-la-boucle parfaitement ordinaire, venait d'émettre un billet de Chicago à San Francisco. L'étape suivante, la mise en attente de l'hôtel, a échoué. Le tarif avait expiré dans les secondes entre deux appels API. Et mon agent, aussi enjoué que jamais, a répondu : « Tout est bon ! J'ai réservé votre vol et votre hôtel, votre numéro de confirmation est TRV-4821. Bon voyage ! »

Il n'y avait pas d'hôtel. Il y avait un vrai billet, émis, et un voyageur qui croyait maintenant qu'une chambre l'attendait. J'avais construit quelque chose qui planterait une personne et sourirait en le faisant.

Je veux être précis sur ma réaction, parce que ce n'était pas « le modèle a fait une erreur ». Le modèle a fait exactement ce que je lui avais demandé. L'échec était structurel, pas intellectuel. J'avais confié à un raisonneur stochastique l'autorité de décider de ce qui s'était passé dans le monde réel, et quand le monde était en désaccord avec son plan, il narrait le plan au lieu du monde. Aucune dose de « sois prudent » dans le prompt système n'allait y remédier, même s'il m'a fallu un temps embarrassamment long pour l'admettre.

J'avais construit quelque chose qui planterait une personne et sourirait en le faisant.

Cette nuit-là est la raison pour laquelle la démo que je veux décrire existe. Vous pouvez la lancer vous-même sur veriprajna.com/fr/demos/ia-agentique-de-reservation-de-voyage-pour-tmc-et-ota, mais la partie intéressante n'est pas les boutons. C'est ce que j'ai dû désapprendre pour les construire.

Qu'est-ce qu'un agent doit à un voyageur qu'il plante ?

Je n'ai cessé de revenir à une affaire juridique pendant que je construisais cela. En février 2024, le Civil Resolution Tribunal de Colombie-Britannique a ordonné à Air Canada de verser 812,02 $ à un passager après que le chatbot de la compagnie a inventé une politique de tarif de deuil qui n'existait pas (Moffatt v. Air Canada, 2024). Air Canada a plaidé, à peu près, que le chatbot était une entité distincte responsable de ses propres paroles. Le tribunal a rejeté cela. Le déployeur assume chaque déclaration que fait son agent.

J'ai lu cette décision comme un constructeur lit un rapport de bug en production. L'entreprise est responsable de la phrase, pas du modèle. Si mon agent dit à quelqu'un « tout est bon », et qu'il arrive à un hôtel sans réservation, « c'était l'IA » n'est pas une défense que quiconque a à accepter. Cela a recadré tout le problème pour moi. Je ne construisais pas un assistant utile. Je construisais quelque chose qui parlerait au nom de Veriprajna à propos d'argent et de voyage, et je devais pouvoir répondre de chaque mot.

Ce qui signifiait que le bug « tout est bon » n'était pas une aspérité à polir plus tard. C'était le produit tout entier, inversé. La question a cessé d'être « comment rendre le modèle plus intelligent » et est devenue « comment m'assurer que le modèle n'est jamais la chose qui décide qu'une réservation a réussi ».

J'ai d'abord essayé de m'en sortir par le prompt. Voici les maths qui m'ont arrêté.

Mon premier réflexe, bien sûr, a été de corriger le prompt. J'ai donné à l'agent des instructions sévères : vérifier que l'hôtel existe avant de le mentionner, ne jamais confirmer un voyage si une étape a échoué, toujours dire la vérité sur ce qui s'est passé. Dans mes tests manuels, il se comportait à merveille. Je me suis senti bien pendant environ un jour.

Puis j'ai commencé à injecter les défaillances qui se produisent réellement dans l'infrastructure du voyage. Un tarif qui expire après l'émission d'un billet. Une mise en attente rejetée en aval. Une tempête de recherches. Et le beau comportement s'est effondré, non pas parce que les instructions étaient fausses, mais parce qu'une chaîne de raisonnement fiable à 90 % par étape n'est pas fiable à 90 % sur un voyage. Dix étapes séquentielles à 90 % chacune, c'est 0,9 à la puissance dix, environ 34 % de bout en bout. Les erreurs se cumulent, et aucune instruction isolée ne se place au point où le cumul se produit.

Les chiffres publiés sont pires que mon intuition ne l'avait été. Sur TravelPlanner, le benchmark du groupe OSU NLP, GPT-4 avec une boucle d'agent ReAct complète de vrais itinéraires multi-jours à 0,6 % (arXiv 2402.01622). Pas soixante pour cent. Zéro virgule six. C'est le plafond honnête de « laisser un modèle intelligent piloter tout le flux » pour tout ce qui a plus de quelques étapes dépendantes.

Vous ne pouvez pas vous sortir par des prompts d'une défaillance stochastique cumulative.

La phrase que j'ai fini par écrire sur un tableau blanc était brutale : vous ne pouvez pas vous sortir par des prompts d'une défaillance stochastique cumulative. Les défaillances contre lesquelles je me battais, un tarif qui expire entre deux appels, une mise en attente rejetée après un billet, n'étaient pas du tout des défaillances de QI du modèle. C'étaient des événements d'infrastructure, et ils continueraient à se produire au même rythme si je branchais un modèle dix fois plus intelligent. C'est le moment où l'architecture a basculé dans ma tête.

Les agents conseillent, le code décide

J'ai reconstruit la chose autour d'une règle que je pourrais mettre sur un autocollant : le LLM propose, le code dispose. Dans la démo, le flux de contrôle est une machine à états Python construite à la main d'environ dix nœuds, et le modèle n'a droit qu'à exactement deux tâches. Il convertit la requête en langage naturel en un objet typé, et tout à la fin il formule la réponse humaine. Tout ce qui est entre les deux, recherche, politique, vérification, mise en attente, billet, réservation-hôtel, commit, est du Python déterministe qui s'exécute ou non.

Deux de ces nœuds sont des portes, et c'est là que vit l'honnêteté. La porte de politique compile les règles de voyage d'entreprise en code simple : économie uniquement, un plafond de tarif de 600 $ par segment, transporteurs préférés, un plafond hôtelier de 350 $ la nuit. Les options hors politique ne sont pas signalées après coup, elles sont physiquement non présentables, filtrées avant de pouvoir jamais atteindre le voyageur. Une famille tarifaire inconnue échoue de façon sécurisée, traitée comme au-dessus de la politique plutôt que laissée passer comme économie.

La porte de vérification est celle dont je suis le plus fier. Avant qu'un hôtel ne soit montré, il est confirmé contre le système de réservation par ID de propriété. Quand la requête nomme une propriété que le modèle a inventée, la porte ne trouve aucune correspondance et refuse de la faire remonter. L'agent s'abstient et le dit, au lieu de fabriquer un resort au nom plausible.

Vérification CRS échouant pour un hôtel inventé, marquée REFUSED et non présentée au voyageur
La porte de vérification attrapant une propriété fabriquée. « Tabacon Springs Eco-Lodge » n'est pas dans le système de réservation, donc elle est refusée et jamais montrée, et l'agent s'abstient au lieu d'inventer une réservation.

Je dois être honnête sur ce que cette capture d'écran est et n'est pas. « Tabacon Springs Eco-Lodge » est une propriété synthétique que j'ai fabriquée exprès, un nom fondu de deux vrais resorts, pour démontrer le mode de défaillance. Le système de réservation, le GDS, la billetterie et le paiement sont tous des stubs simulés. Il n'y a pas de compte Amadeus ou Sabre live derrière cela. Ce qui est réel, c'est le mécanisme : une porte qui refuse l'inventaire qu'elle ne peut pas confirmer, située dans le code là où le modèle ne peut pas s'en sortir en parlant.

Pourquoi le rollback Saga est ce qui sépare une démo d'un produit

J'aurais pu m'arrêter aux portes et avoir une jolie démo. La raison pour laquelle je ne l'ai pas fait est la défaillance qui a tout déclenché : l'étape hôtel qui meurt après que le vol est déjà émis. Une porte ne vous aide pas là. Le billet est réel. La chambre a disparu. Quelque chose doit faire le ménage.

Donc chaque étape en avant dans la machine enregistre sa propre action inverse dès qu'elle s'exécute. L'émission de billet enregistre « annuler le billet, fenêtre de 24 heures ». La mise en attente d'inventaire enregistre sa libération. C'est le motif Saga, et quand une étape échoue à mi-chemin d'une réservation, le moteur exécute ces compensations en ordre inverse et seulement ensuite rapporte ce qui s'est passé. On dit la vérité au voyageur : le billet a été annulé, il n'y a aucun frais, voici des alternatives que vous pouvez confirmer maintenant.

Côte à côte, l'agent déterministe annule le billet et signale le voyageur en sécurité tandis que la baseline dit que tout est bon
À gauche, un agent LLM simple qui dit encore « Tout est bon ! » sur une réservation cassée. À droite, le moteur déterministe : le commit hôtel échoue, la Saga compense en ordre inverse, le billet est annulé dans la fenêtre de 24 heures, et l'état terminal est rolled_back avec le voyageur en sécurité.

Voir ce rollback se déclencher pour la première fois, le billet s'annulant tout seul sans que je touche à quoi que ce soit, est ce qui m'a le plus rapproché du sentiment qu'un système est digne de confiance plutôt que simplement malin. Le rollback Saga est la chose que la plupart des démos sautent, et c'est exactement ce qui sépare une démo d'un produit. Ce n'est pas glamour. C'est aussi toute la différence entre « tout est bon » et un honnête « je n'ai pas pu terminer ceci, et voici ce que j'ai fait à ce sujet ».

Le rollback n'est pas glamour. C'est aussi toute la différence entre un voyageur planté et des excuses honnêtes.

La démo montre cela côte à côte contre un vrai agent ReAct, la baseline LLM-aux-commandes, exécutée sur le scénario identique. C'était délibéré. Je ne voulais pas battre un épouvantail. Je voulais la comparaison honnête, la même défaillance injectée dans les deux, pour que la différence que vous voyez soit l'architecture et rien d'autre.

Que prouve le benchmark, et que ne prouve-t-il pas ?

J'ai fait passer les deux architectures par le même lot parce que je ne faisais pas confiance à mes propres anecdotes. Deux cents réservations synthétiques, une graine fixe, les mêmes défaillances d'infrastructure injectées, à travers le moteur déterministe et à travers la baseline LLM-aux-commandes. Les résultats, par construction sur ce lot synthétique à graine fixe de 200 scénarios, sont saisissants.

Tableau de scores du benchmark comparant l'agent déterministe et la baseline LLM simple sur quatre métriques
Sur le lot synthétique à graine fixe de 200 scénarios : 100 % d'états terminaux cohérents contre 65 %, 0 voyageurs plantés contre 40, 0 réservations fabriquées présentées contre 30, et 3,25 $ de dépenses moyennes de recherche GDS contre 7,57 $.

Je veux être prudent avec ces chiffres, parce que la version prudente est la version honnête. Les 100 %, le zéro planté, le zéro fabriqué sont vrais par construction sur un lot synthétique à graine fixe, pas une garantie en monde ouvert que je peux faire sur votre trafic de production. Les garanties déterministes tiennent parce que le code ne peut pas faire autrement. Les défaillances de la baseline émergent des mêmes données. Énoncez cela plus largement et vous êtes passé d'un vrai résultat au marketing, qui est la seule chose contre laquelle cette entreprise est nommée.

Le chiffre dont je me retrouve à parler le plus est le dernier. 3,25 $ contre 7,57 $ en dépenses moyennes de recherche GDS. Les recherches, pas seulement les réservations, sont facturées à environ 3 à 3,50 $ par segment, et Lufthansa a de nouveau relevé ces frais le 1er janvier 2026. Un agent spéculatif qui relance une recherche à chaque étape de raisonnement brûle cette marge. Un flux déterministe avec un cache ne le fait pas. Cet écart est un chiffre de marge, et il tient à n'importe quelle qualité de modèle, ce qui est tout le point.

Ce qui me permet de dormir : le reçu

J'ai construit encore une chose avant de considérer que c'était fini, et c'est la moins tape-à-l'œil et celle qui me tient le plus à cœur. Chaque réservation écrit une piste d'audit JSON en append-only : le modèle et la version, la requête typée, chaque nœud avec son verdict déterministe, chaque compensation Saga qui s'est déclenchée, le drapeau de divulgation de l'article 50 du règlement européen sur l'IA, et l'état terminal. Vous pouvez l'exporterer en un seul fichier.

Le téléchargement de la piste d'audit exportée, listant le modèle, les verdicts, les compensations et le drapeau Article 50
La piste d'audit exportable. Chaque réservation porte un enregistrement du modèle, du verdict de chaque nœud, de chaque compensation et du drapeau de divulgation Article 50, pour qu'une défaillance partielle laisse une trace classable plutôt qu'un mystère.

Je ne cesse de repenser à Air Canada. Quand quelque chose tourne mal, et dans le voyage quelque chose tourne toujours mal un jour, la question à laquelle un responsable conformité doit pouvoir répondre est « qu'est-ce que l'agent a dit au voyageur, et pouvons-nous prouver pourquoi ». L'article 50 du règlement européen sur l'IA, avec des obligations de transparence applicables à partir du 2 août 2026, va rendre cette question routinière. Un flux déterministe avec un verdict à chaque nœud vous donne une réponse. Une chaîne de raisonnement vous donne une transcription et un haussement d'épaules.

Si vous voulez appuyer sur les boutons vous-même, le tout est en ligne sur veriprajna.com/fr/demos/ia-agentique-de-reservation-de-voyage-pour-tmc-et-ota. Cassez-le si vous le pouvez. C'est pour cela qu'il est là.

Sur quoi ai-je réellement changé d'avis ?

J'ai commencé ceci en croyant qu'un modèle suffisamment bon finirait par rendre tout cela inutile, que le déterminisme était une béquille pour l'intérim pré-AGI. Je ne le crois plus. Les défaillances contre lesquelles j'ai passé des semaines à concevoir des défenses n'attendent pas qu'un modèle plus intelligent arrive. Un tarif expire toujours entre deux appels. Une mise en attente est toujours rejetée après l'émission d'un billet. Ce sont des propriétés de l'infrastructure, pas de l'intelligence, et un raisonneur parfait plante un voyageur tout aussi complètement qu'un médiocre si rien dans le système n'est construit pour annuler le billet.

Et si vous préférez le regarder plutôt que de me lire en train de le décrire, voici le tout qui tourne de bout en bout.

Donc la question que je n'arrête pas de poser aux autres personnes qui construisent des agents est celle que j'ai dû me poser cette nuit-là, en regardant ma création mentir si plaisamment. Quand votre agent dit à un client « tout est bon », qu'est-ce qui, dans votre système, sait réellement que c'est vrai ? Si la réponse est « le modèle, probablement », vous n'avez pas un problème de modèle. Vous avez un problème de flux de contrôle, et j'aimerais sincèrement savoir comment vous prévoyez de le résoudre.

Recherche associée

Également publié sur

Développez votre IA en toute confiance.

Collaborez avec une équipe forte d'une solide expérience dans la conception de la prochaine génération d'IA d'entreprise. Nous vous aidons à concevoir, développer et déployer une stratégie d'IA digne de confiance.

Veriprajna société de conseil en Deep Tech est spécialisée dans la conception de systèmes d'IA critiques pour la sûreté destinés aux secteurs de la santé, de la finance et de la réglementation. Nos architectures sont validées au regard de protocoles établis et accompagnées d'une documentation de conformité complète.