Actions utilisateur
Mis à jour le 29 juillet 2026
Actions utilisateur
Les actions utilisateur permettent à vos utilisateurs d’interagir avec l’agent au-delà du texte libre. Boutons de suggestions, actions rapides, confirmations, formulaires inline : ces interactions guidées améliorent l’expérience et réduisent les erreurs. Le raisonnement est simple — chaque fois que l’utilisateur doit deviner comment formuler sa demande, vous perdez un tour de conversation et parfois l’utilisateur lui-même.
Actions de suggestion
Les suggestions apparaissent avant que l’utilisateur tape un message, et elles règlent le problème de la page blanche. Face à un champ vide, la moitié des utilisateurs écrivent « bonjour » ou ferment la fenêtre ; face à quatre propositions, ils cliquent. Choisissez-les en fonction de ce que votre agent sait réellement faire : chaque suggestion est une promesse, et une promesse non tenue au premier message coûte plus cher qu’une absence de suggestion.
import { ChatProvider, ChatWindow, MessageInput } from "@openai/chatkit/react";
function ChatAvecSuggestions() {
const suggestions = [
{ label: "Voir mes commandes", message: "Montrez-moi mes commandes récentes" },
{ label: "Contacter le support", message: "J'ai besoin d'aide avec un problème" },
{ label: "Mes factures", message: "Affichez mes dernières factures" },
{ label: "Statut de livraison", message: "Où en est ma livraison ?" },
];
return (
<ChatProvider endpoint="/api/chat">
<ChatWindow
welcomeMessage="Bonjour ! Comment puis-je vous aider aujourd'hui ?"
suggestions={suggestions}
/>
<MessageInput />
</ChatProvider>
);
}
Notez la dissociation entre label et message : l’étiquette reste courte pour tenir sur un bouton, tandis que le message envoyé à l’agent est rédigé comme une vraie demande. C’est ce qui vous permet d’afficher « Mes factures » tout en transmettant une phrase que l’agent interprétera sans ambiguïté.
Actions inline dans les messages
Les suggestions valent pour l’ouverture ; ensuite, c’est l’agent qui propose. Un tool peut renvoyer une liste d’actions contextuelles sous la clé __actions, chacune décrite par un identifiant, un libellé, une icône, éventuellement un style, et le message à envoyer si l’utilisateur clique. Sur une commande livrée, proposer « Suivre la livraison », « Voir la facture » et « Demander un retour » couvre l’essentiel des intentions suivantes sans que l’utilisateur ait à les formuler.
import json
from agents import function_tool
@function_tool
def proposer_actions_commande(commande_id: str) -> str:
"""Propose des actions pour une commande."""
return json.dumps({
"__actions": [
{
"id": "suivre",
"label": "Suivre la livraison",
"icon": "truck",
"message": f"Suivre la livraison de la commande {commande_id}",
},
{
"id": "facture",
"label": "Voir la facture",
"icon": "document",
"message": f"Afficher la facture de la commande {commande_id}",
},
{
"id": "retour",
"label": "Demander un retour",
"icon": "return",
"style": "outline",
"message": f"Initier un retour pour la commande {commande_id}",
},
]
})
L’identifiant de commande est interpolé dans chaque message : le clic transporte donc le contexte, et l’agent n’a jamais à redemander « de quelle commande parlez-vous ? ». Côté frontend, rendez ces actions comme des boutons.
function ActionsWidget({ data, onAction }) {
return (
<div style={{
display: "flex",
flexWrap: "wrap",
gap: "8px",
margin: "12px 0",
}}>
{data.__actions.map((action) => (
<button
key={action.id}
onClick={() => onAction("send_message", { content: action.message })}
style={{
padding: "8px 16px",
background: action.style === "outline" ? "transparent" : "#2563EB",
color: action.style === "outline" ? "#3B82F6" : "white",
border: action.style === "outline" ? "1px solid #3B82F6" : "none",
borderRadius: "8px",
cursor: "pointer",
fontSize: "13px",
}}
>
{action.label}
</button>
))}
</div>
);
}
Le style outline prend ici tout son sens : la demande de retour, plus engageante que la simple consultation d’une facture, s’affiche en contour et non en bouton plein. Le flexWrap garantit pour sa part que trois boutons ne débordent pas d’un panneau étroit.
Formulaires inline
Certaines informations ne se collectent pas en conversation. Demander une raison de retour puis une description en deux tours d’échange, c’est deux occasions de perdre l’utilisateur et deux réponses hors sujet à rattraper. Un formulaire affiché dans le fil règle la question : l’utilisateur voit d’un coup ce qu’on lui demande, remplit dans l’ordre qu’il veut, et soumet une fois. Le composant maintient les valeurs saisies dans son état local, puis transmet l’ensemble via onAction au moment de la soumission.
import { useState } from "react";
function FormulaireWidget({ data, onAction }) {
const [valeurs, setValeurs] = useState({});
const handleSubmit = () => {
onAction("submit_form", {
formId: data.formId,
values: valeurs,
});
};
return (
<div style={{
padding: "16px",
background: "#1E293B",
borderRadius: "12px",
margin: "8px 0",
}}>
<h4 style={{ color: "#F8FAFC", margin: "0 0 12px" }}>{data.titre}</h4>
{data.champs.map((champ) => (
<div key={champ.id} style={{ marginBottom: "12px" }}>
<label style={{ display: "block", color: "#94A3B8", fontSize: "12px", marginBottom: "4px" }}>
{champ.label}
</label>
<input
type={champ.type || "text"}
placeholder={champ.placeholder}
onChange={(e) => setValeurs({ ...valeurs, [champ.id]: e.target.value })}
style={{
width: "100%",
padding: "8px 12px",
background: "#0F172A",
border: "1px solid #475569",
borderRadius: "8px",
color: "#F8FAFC",
}}
/>
</div>
))}
<button
onClick={handleSubmit}
style={{
width: "100%",
padding: "10px",
background: "#2563EB",
color: "white",
border: "none",
borderRadius: "8px",
cursor: "pointer",
}}
>
{data.submitLabel || "Envoyer"}
</button>
</div>
);
}
Le formulaire n’est pas codé en dur : sa structure vient du tool, qui décrit le titre, la liste des champs et le libellé du bouton. Vous pouvez donc en créer d’autres — changement d’adresse, réclamation, prise de rendez-vous — sans écrire une ligne de React supplémentaire.
@function_tool
def demander_informations_retour() -> str:
"""Affiche un formulaire pour demander les informations de retour."""
return json.dumps({
"__widget": "formulaire",
"formId": "retour-produit",
"titre": "Demande de retour",
"champs": [
{"id": "raison", "label": "Raison du retour", "placeholder": "Ex: produit défectueux"},
{"id": "description", "label": "Description", "placeholder": "Décrivez le problème..."},
],
"submitLabel": "Soumettre la demande",
})
Confirmations
Reste le cas des actions irréversibles. Un agent qui annule une commande sur la foi d’un « oui » ambigu vous vaudra un ticket de support et un client mécontent. Avant ce type d’action, faites passer l’utilisateur par une confirmation explicite : un titre, un message qui nomme la conséquence, et deux boutons dont le libellé se comprend hors contexte. « Oui, annuler » et « Non, garder la commande » valent mieux qu’« OK » et « Annuler », ce dernier étant justement le mot le plus ambigu qui soit dans un dialogue d’annulation.
@function_tool
def confirmer_annulation(commande_id: str) -> str:
"""Demande confirmation avant d'annuler une commande."""
return json.dumps({
"__widget": "confirmation",
"titre": "Confirmer l'annulation",
"message": f"Voulez-vous vraiment annuler la commande {commande_id} ? Cette action est irréversible.",
"actions": [
{"id": "confirmer", "label": "Oui, annuler", "style": "danger"},
{"id": "annuler", "label": "Non, garder la commande", "style": "secondary"},
],
})
Le style danger sur le bouton destructeur et secondary sur le retrait complètent le dispositif visuellement. Gardez toutefois en tête que cette confirmation reste une couche d’interface : la vérification qui fait autorité doit exister aussi côté serveur, sujet que nous reprendrons dans la leçon sur la sécurité en production.
Points clés à retenir
- Les suggestions guident l’utilisateur dès le premier message
- Les actions inline proposent des choix contextuels dans les réponses
- Les formulaires inline collectent des données structurées sans quitter le chat
- Les confirmations protègent contre les actions irréversibles
- Chaque action envoie un message structuré à l’agent via
onAction