1. Qu’est‑ce que les follow‑ups dans l’application ChatGPT et à quoi servent‑ils
Commençons par une définition en langage humain, pas marketing. Un follow‑up dans le contexte de l’application ChatGPT est une étape suivante du dialogue initiée par le programme. C’est généralement une courte suggestion présentée sous forme de bouton : au clic, elle devient un nouveau message texte de la part de l’utilisateur dans le chat et lance la suite du scénario entre l’humain et l’IA.
Du point de vue du modèle, un follow‑up n’est qu’un autre message utilisateur. Pas de magie : quand l’utilisateur clique sur votre bouton « Afficher des options moins chères », quelque chose comme « Montre des cadeaux moins chers » arrive dans l’historique du chat. Le modèle le voit comme une phrase ordinaire d’utilisateur, applique le system‑prompt et les descriptions des tools, décide quel outil appeler et, éventuellement, re‑rend votre widget avec d’autres données.
Pourquoi c’est important :
- Le modèle raisonne en termes de texte. Si, au clic, vous appelez simplement un outil directement (sans message), vous contournez le « cerveau » principal du système et perdez une partie du contexte. Le follow‑up conserve la progression de la conversation dans l’historique et aide le modèle à comprendre ce qui se passe.
- L’utilisateur reste dans le paradigme familier du chat : soit il écrit des messages, soit il appuie sur des suggestions. Les follow‑ups sont des « réponses rapides » (quick replies), comme dans les messageries modernes.
- C’est le pont principal entre votre UI et la partie textuelle de ChatGPT. Sans follow‑ups, le widget devient une île muette : l’utilisateur clique et ne comprend pas bien ce qu’il doit faire ensuite.
On peut voir les follow‑ups comme un bouton « Prochaine question à l’IA », mais formulée par vous. Ensuite, nous considérerons les follow‑ups non pas comme « une autre fonctionnalité UI », mais comme la manière principale d’orchestrer le dialogue autour du widget.
2. « Dialogue autour du widget » : sandwich conversationnel
Pour visualiser comment les follow‑ups aident à construire un « dialogue autour du widget », il est utile d’imaginer le dialogue comme un sandwich à trois couches :
- en haut, le texte de ChatGPT avant le widget (pré‑texte),
- au milieu, votre widget (UI),
- en bas, les follow‑ups et les messages suivants (post‑interaction).
Schématiquement :
sequenceDiagram
participant U as Utilisateur
participant G as ChatGPT
participant W as Widget
U->>G: "Trouve un cadeau pour ma sœur pour moins de 100 $"
G->>G: Décide d’appeler l’app
G->>U: Pre-text: "Je vais ouvrir GiftGenius et chercher des idées"
G->>W: Transmet toolOutput au rendu
W-->>U: Cartes cadeau + boutons follow-up
U->>W: Clic sur "Afficher des options moins chères"
W->>G: sendFollowUpMessage("Montre des cadeaux moins chers, jusqu’à 50 $")
G->>G: Nouveau passage du modèle, appel des tools
G->>W: Nouveau toolOutput, widget mis à jour
Le pré‑texte est généralement entièrement généré par le modèle à partir du system‑prompt et du contexte : il « explique » ce qui va se passer (« Je vais ouvrir une application qui aide à choisir un cadeau »). Nous verrons comment le contrôler plus tard, dans le module sur les instructions.
Le widget est votre composant React habituel : il affiche toolOutput, utilise widgetState, fournit des boutons et des choix.
La couche post‑interaction est ce dont nous nous occupons aujourd’hui. Avec les follow‑ups et l’envoi de messages, vous tracez la suite claire : « Afficher plus cher », « Modifier le budget », « Recommencer la sélection », « Passer à la commande ».
En simplifiant, un follow‑up est une réplique de pilotage qui boucle le cycle : UI → texte → nouveau widget.
3. Modèle technique : comment un clic sur un follow‑up se transforme en un nouvel appel d’outil
Regardons de près la chaîne d’événements « sous le capot ». C’est commode de l’envisager comme un cycle d’interaction hybride : clic → API → texte dans l’historique → nouvelle décision du modèle → nouvel appel d’outil → UI mise à jour.
La séquence ressemble à ceci :
- L’utilisateur clique sur un bouton dans votre widget.
- Le widget appelle l’API window.openai.sendFollowUpMessage ou, dans la couche React, le hook pratique useSendMessage (dans les exemples ci‑dessous, nous utiliserons ce hook). L’argument est une simple chaîne : le texte comme si l’utilisateur l’avait tapé.
- ChatGPT ajoute ce message à l’historique en tant que nouveau user_message.
- Le modèle effectue un nouveau passage : il prend en compte tout l’historique, y compris le précédent toolOutput, et décide s’il faut appeler un outil, lequel et avec quels arguments.
- Votre backend/MCP exécute l’appel d’outil et renvoie toolOutput.
- ChatGPT affiche la nouvelle réponse : peut‑être à nouveau un widget (avec de nouvelles données), peut‑être du texte, voire une combinaison.
Important : vous ne voulez presque jamais, directement depuis le widget, appeler le même outil que le modèle a appelé, en contournant ce cycle. Sinon, le modèle « perd » une étape : l’historique ne contient pas la requête qui a déclenché l’appel répété. Plus tard, dans des scénarios longs, cela se traduit par un contexte embrouillé.
On peut condenser cela en une formule courte :
User Click → useSendMessage("...") → ChatGPT (LLM) → Tool Call → New toolOutput → Widget rerender
4. Types de follow‑ups et qui les conçoit
Nous avons compris ce qui se passe « sous le capot » après un clic sur un follow‑up. Voyons maintenant quels follow‑ups il est pertinent de proposer à l’utilisateur et quels rôles ils peuvent jouer dans le scénario.
Dans une application réelle, il existe plusieurs « familles » de follow‑ups. Je les classe le long de différents axes : statiques vs dynamiques, par rôle (drill‑down, pivot, commit, etc.).
Pour la pratique, un tableau est plus pratique.
| Type | Ce que ça fait | Exemple de texte/bouton |
|---|---|---|
| Suggestif (Suggestive) | Aide si l’utilisateur ne sait pas quoi demander ensuite | « Afficher d’autres idées », « Affiner par centres d’intérêt » |
| De précision (drill‑down / paramétrique) | Resserre la requête précédente selon des paramètres | « Moins cher », « Uniquement des cadeaux numériques », « Uniquement Nike » |
| Bifurcation (Pivot) | Change de branche de scénario | « Recommencer la sélection », « Afficher des cadeaux pour enfant » |
| De navigation (Navigation) | Fait passer à une autre étape du processus | « Passer à la commande », « Revenir au choix » |
| Finalisation (Commit) | Confirme une action | « Commander ce cadeau », « Enregistrer la sélection » |
Du point de vue de la source des idées, il y a deux grands groupes.
Premièrement, les follow‑ups proposés par l’application elle‑même. Ce sont nos boutons dans le widget, liés à la logique UI et aux données : par exemple « Afficher similaires à [Nom du cadeau] » ou « Filtrer uniquement par l’intérêt travel ». Ces suggestions peuvent être codées en dur (statiques) ou générées dynamiquement à partir du toolOutput (dynamiques).
Deuxièmement, les suggestions « natives » de ChatGPT — de petites puces sous le message que le modèle invente lui‑même. Vous ne les contrôlez pas directement ; considérez‑les comme un bonus gratuit, pas comme un mécanisme fiable. Votre application doit fonctionner même sans elles.
Dans ce cours, c’est surtout le premier groupe qui nous intéresse : les boutons et suggestions que vous dessinez dans votre composant React et qui, au clic, envoient sendFollowUpMessage.
5. Implémentation des follow‑ups dans React : GiftGenius comme exemple
Poursuivons notre application fictive GiftGenius, qui propose des idées de cadeaux. Après l’appel de l’outil get_gift_ideas, le widget reçoit un toolOutput avec une liste de cadeaux. Dans les sujets précédents, nous avons déjà construit une grille de cartes. Ajoutons maintenant une section de follow‑ups.
Supposons que le SDK fournisse les hooks useWidgetProps et useSendMessage. Les noms sont arbitraires ici, mais le concept correspond à la référence :
import { useWidgetProps, useSendMessage } from '@/openai-apps';
export const GiftSuggestions: React.FC = () => {
const { toolOutput } = useWidgetProps();
const sendMessage = useSendMessage();
const gifts = toolOutput?.data?.gifts ?? [];
if (gifts.length === 0) {
return <div>Aucun cadeau trouvé. Essayez de modifier la requête.</div>;
}
const handleCheaper = () => {
sendMessage('Montre des cadeaux moins chers, jusqu’à 50 $');
};
const handleDigital = () => {
sendMessage('Montre uniquement des cadeaux numériques: cartes-cadeaux, abonnements, etc.');
};
return (
<div className="flex flex-col gap-4">
<div className="grid grid-cols-2 gap-2">
{gifts.map((gift: any) => (
<GiftCard key={gift.id} item={gift} />
))}
</div>
<div className="border-t pt-3 text-sm">
<div className="text-xs text-gray-500 mb-2">Que faire ensuite ?</div>
<div className="flex flex-wrap gap-2">
<button
onClick={handleCheaper}
className="px-3 py-1 rounded-full bg-gray-100 hover:bg-gray-200"
>
Moins cher
</button>
<button
onClick={handleDigital}
className="px-3 py-1 rounded-full bg-gray-100 hover:bg-gray-200"
>
Numérique uniquement
</button>
</div>
</div>
</div>
);
};
Plusieurs points sont importants ici.
Premièrement, sendMessage reçoit une chaîne — ce texte apparaîtra dans le chat comme si l’utilisateur l’avait saisi. Votre application ne doit pas imiter un « protocole système interne » ; formulez simplement les phrases pour que le modèle les comprenne.
Deuxièmement, la section des follow‑ups est visuellement séparée (bordure supérieure, petit texte « Que faire ensuite ? »), afin que l’utilisateur comprenne qu’il s’agit plutôt de la suite du dialogue que d’éléments de la carte elle‑même.
Troisièmement, peu de boutons — deux. Les recommandations UX suggèrent de rester dans une fourchette d’environ deux à quatre options : suffisant pour aider, sans surcharger.
Follow‑up dynamique basé sur les données
Supposons que vous vouliez permettre à l’utilisateur d’approfondir un cadeau précis : « Afficher similaires à celui‑ci ». Le texte du follow‑up doit alors mentionner l’objet concerné, et vous pouvez générer ce texte à la volée.
const handleShowSimilar = (giftTitle: string) => {
sendMessage(
`Montre des cadeaux similaires à "${giftTitle}", dans le même budget ou un peu plus cher`
);
};
Et dans la carte :
<button
onClick={() => handleShowSimilar(gift.title)}
className="mt-2 text-xs text-blue-600 underline"
>
Afficher similaires
</button>
Ainsi, vous implémentez un follow‑up dynamique, lié à des données précises issues de toolOutput. Ce sont justement ces boutons qui rendent le dialogue « intelligent », et pas seulement une suite générique « Suivant / Précédent ».
6. Pourquoi envoyer du texte plutôt que d’appeler l’outil directement
Réflexe typique d’un développeur front‑end : « Puisque j’ai useCallTool, pourquoi envoyer du texte ? Je peux directement appeler get_gift_ideas avec d’autres paramètres. » Parfois, c’est effectivement nécessaire (nous y reviendrons dans le module sur l’appel d’outils (tools) depuis le widget), mais par défaut il vaut mieux passer par un follow‑up textuel. Les raisons sont très pratiques.
Premièrement, l’historique du chat reste cohérent. Vu de l’extérieur, tout ressemble à « Montre des cadeaux moins chers » écrit par l’utilisateur lui‑même. Une semaine plus tard, il rouvrira l’historique et comprendra ce qui s’est passé. Si vous aviez tout fait via des appels directs d’outils, divers widgets apparaîtraient soudainement entre les messages de l’utilisateur sans raison apparente.
Deuxièmement, le modèle peut prendre des décisions supplémentaires. Par exemple, comprendre qu’au lieu de rappeler le même outil, il vaut mieux d’abord clarifier le budget : « Êtes‑vous sûr de vouloir réduire le budget à 5 $ ? On peut peut‑être garder au moins 20 $ ? » Ces scénarios flexibles deviennent impossibles si vous codez en dur « clic → même outil avec d’autres arguments ».
Troisièmement, le modèle peut appeler un tout autre outil. Supposons que l’utilisateur clique sur « Contacter le support », et que votre system‑prompt apprenne au modèle qu’il faut dans ce cas appeler create_support_ticket, et non get_gift_ideas. Un follow‑up textuel donne au modèle la liberté de basculer vers un autre outil.
D’où la règle pratique du module 3 : au clic dans l’UI, dans la plupart des cas on envoie un follow‑up textuel, pas un appel direct à l’outil. Les appels directs d’outils depuis le widget sont à réserver aux cas spécifiques où nous n’avons définitivement pas besoin d’une nouvelle étape utilisateur dans l’historique.
7. Liaison des follow‑ups et des états : éviter de désynchroniser l’UI et le texte
Problème intéressant : l’UI « vit » sa propre vie, et le texte dans le chat — la sienne. Supposons qu’au clic vous changiez un filtre dans le widget et envoyiez en même temps un follow‑up. Si vous avez seulement mis à jour l’UI sans figer le nouvel état via widgetState, au prochain rendu ChatGPT restaurera l’ancien widgetState. Résultat : le widget réaffiche les anciens filtres, alors que l’historique contient déjà l’étape « moins cher ». L’expérience est étrange.
Bon motif de conception : au clic sur un follow‑up, simultanément :
- mettre à jour widgetState,
- envoyer le message de follow‑up.
Exemple :
import { useWidgetState, useSendMessage } from '@/openai-apps';
type GiftWidgetState = {
priceFilter?: 'any' | 'cheap' | 'premium';
};
export const GiftFollowups: React.FC = () => {
const [widgetState, setWidgetState] = useWidgetState<GiftWidgetState>();
const sendMessage = useSendMessage();
const handleCheaper = () => {
setWidgetState({ ...widgetState, priceFilter: 'cheap' });
sendMessage('Montre des cadeaux moins chers, environ 50 $');
};
// ...
};
À présent, ChatGPT et votre UI savent que le filtre a changé. Si le modèle reconstruit le widget plus tard, il verra le widgetState mis à jour et pourra, par exemple, générer un nouveau pré‑texte du type « Voici des idées plus budget ».
8. Concevoir de bons follow‑ups
Un bon follow‑up est la moitié du succès UX. Il n’est pas seulement « joli », il économise l’énergie cognitive de l’utilisateur.
Quelques principes pratiques méritent d’être affichés au‑dessus de l’écran.
Premièrement, la concision. Un follow‑up n’est pas l’endroit pour une tirade. Une courte phrase, compréhensible sans le contexte de l’UI, est généralement idéale : « Moins cher », « Premium uniquement », « Changer de destinataire ». Si vous avez besoin de plus long, demandez‑vous si ce ne devrait pas être un texte GPT classique plutôt qu’un bouton.
Deuxièmement, l’orientation action. Formulez de sorte que l’on sache ce qui va se passer. « Plus d’idées » — correct. « Plus de détails sur le point 2 » — mieux le reformuler en « Donne‑moi plus de détails sur la deuxième option » (ainsi le modèle comprend de quoi il s’agit, même sans l’UI).
Troisièmement, la continuité du scénario, pas sa répétition. Au lieu de « Relancer la sélection de cadeau », préférez « Modifier le budget » ou « Changer les hobbies du destinataire ». Le follow‑up doit faire avancer l’utilisateur — ou le dévier —, pas le ramener au point de départ sans nécessité.
Quatrièmement, une quantité limitée. Deux à quatre boutons sous le widget — presque toujours suffisant. Une plaque de dix options devient un examen de la destinée : l’utilisateur se perd et ne clique sur rien.
Enfin, respectez la tonalité. Si toute l’application s’exprime de manière conviviale, il serait étrange d’insérer un bouton « CONFIRMER LA COMMANDE » en majuscules. Le follow‑up fait partie du même dialogue que le texte du modèle ; le style doit rester cohérent.
9. Les « dialogues autour du widget » en général : qui fait quoi
Il est important de ne pas considérer le widget comme le « héros principal » et ChatGPT comme un « cadre autour ». C’est l’inverse : le modèle continue de mener le dialogue, et le widget n’est qu’un moyen de présenter et d’ajuster les données.
Scénario typique pour GiftGenius :
- Utilisateur : « J’ai besoin d’un cadeau pour ma sœur développeuse jusqu’à 100 $ ».
- Modèle : texte d’introduction (pré‑texte) — explique qu’il va ouvrir GiftGenius et ce qu’il fait.
- Widget : affiche une sélection d’idées, propose des follow‑ups.
- Utilisateur : soit il écrit un message lui‑même, soit il clique sur un bouton de follow‑up (par exemple « Afficher uniquement des cadeaux numériques »).
- Modèle : interprète cela comme du texte, appelle l’outil pertinent, commente si nécessaire le résultat (post‑texte) ou ré‑affiche un widget.
- Et ainsi de suite, jusqu’à ce que la tâche soit accomplie — jusqu’à la confirmation du choix, la commande, etc.
Les follow‑ups sont la colle qui relie chaque boucle de ce cycle. Sans eux, après le widget, l’utilisateur reste en suspens : c’est joli, mais « que faire ensuite ? » reste flou.
Dans des scénarios plus complexes (workflows, agents), les follow‑ups aident à modéliser des entonnoirs multi‑étapes : « Choisissez d’abord le destinataire », « Maintenant, précisez le budget », « Confirmez le choix ». Mais dans ce module, l’important est de voir que même la plus simple application en une étape bénéficie grandement de quelques suggestions bien pensées.
10. Pratique : ce que vous pouvez faire dès maintenant
Un bon exercice de consolidation consiste à améliorer votre widget d’apprentissage actuel.
Si vous avez déjà une liste de résultats (par exemple, des cadeaux, des hôtels ou des documents), ajoutez en dessous un petit bloc « Que faire ensuite ? » avec deux ou trois boutons. Essayez d’aligner ces boutons sur les types du tableau ci‑dessus : l’un doit être de précision (drill‑down, par exemple « Moins cher »), un autre — une bifurcation (pivot, « Changer de destinataire »), un troisième — si nécessaire — de navigation (« Passer à la commande »).
Dans les gestionnaires de clics, appelez useSendMessage avec un texte pertinent en langage naturel, n’oubliez pas de mettre à jour widgetState si besoin. Relancez ensuite le scénario dans ChatGPT et observez le dialogue : à quel point est‑il devenu plus clair quoi faire après le widget.
Essayez aussi de créer volontairement de mauvais follow‑ups : longs, flous, avec une dizaine d’options — puis comparez les ressentis. C’est un moyen rapide de sentir la différence.
11. Erreurs courantes avec les follow‑ups
Erreur n° 1 : widget « silencieux ».
Le développeur réalise une excellente UI, mais ne propose aucun follow‑up. L’utilisateur voit des cartes, pense « c’est sympa », et doit ensuite deviner par lui‑même qu’il peut, par exemple, demander : « Montre moins cher » ou « Change le destinataire ». La plupart des gens ne devinent pas et partent. Un minimum d’une ou deux suggestions « et maintenant » sous le widget règle ce problème.
Erreur n° 2 : trop de boutons.
L’extrême inverse — inonder l’utilisateur d’une dizaine d’options : « Modifier le budget », « Modifier les centres d’intérêt », « Changer de devise », « Enregistrer la sélection », « Partager avec un ami », « Afficher similaires », « Contacter le support », etc. On obtient un « buffet suédois » psychologique où le choix est difficile. Mieux vaut commencer par les deux ou trois actions les plus fréquentes, et laisser le reste au modèle et au texte libre.
Erreur n° 3 : logique de dialogue uniquement côté front‑end.
Parfois, on tente « d’optimiser » et, au lieu d’envoyer un follow‑up via useSendMessage (ou le bas niveau sendFollowUpMessage), on appelle directement le même outil depuis le widget, en ne mettant à jour que l’UI. L’historique du chat ne contient alors rien sur ce qui s’est passé. Au bout de quelques étapes, le modèle commence à se perdre — et vous avec. La bonne voie : garder la logique de dialogue au niveau du texte et des outils, et le widget comme une fine couche UI.
Erreur n° 4 : formulations ambiguës ou peu claires.
Un bouton « Plus » sans contexte peut vouloir dire n’importe quoi : plus de cadeaux, plus de texte, plus d’argent ? De même, des formulations comme « Recalculer » ou « Reconstruire » sont peu claires pour le modèle comme pour l’utilisateur. Les meilleurs follow‑ups sont concrets : « Afficher plus d’options dans ce budget », « Afficher uniquement des cadeaux numériques ».
Erreur n° 5 : UI et texte désynchronisés.
Classique : au clic sur « Moins cher », vous avez mis à jour le filtre de l’UI, mais vous n’avez pas envoyé de follow‑up dans le chat ou vous n’avez pas mis à jour widgetState. Résultat : aucun pas sur la modification de budget dans l’historique, et au prochain rendu du widget, le filtre « revient en arrière ». On a l’impression d’une interface « cassée ». Utilisez la combinaison setWidgetState + sendMessage pour que le texte et l’UI avancent de concert.
Erreur n° 6 : tenter de contrôler les suggestions « natives » de ChatGPT.
Certains développent en comptant sur le fait que ChatGPT va générer de lui‑même les bonnes puces de follow‑up sous le message, et n’ajoutent pas les leurs. Mais ces suggestions ne sont pas garanties et ne sont pas pilotées par l’application. Considérez‑les comme un bonus agréable, mais fournissez toujours vos propres boutons de follow‑up essentiels dans le widget.
GO TO FULL VERSION