Les clients voient un état honnête d'attente ou de reconnexion et les messages acceptés ne sont ni dupliqués ni supprimés silencieusement.
Utiliser des idempotency keys stables
Générez une idempotency key pour chaque intention utilisateur et gardez-la jusqu'à ce que le SDK signale un résultat accepté. Le moteur natif stocke le corps exact, l'horodatage et la clé dans l'outbox durable du compte avant de résoudre l'écriture. Ne générez pas une nouvelle clé parce que l'accusé de réception tarde.
Le widget web possède sa propre interface d'attente et de reconnexion. Les clients mobiles headless exposent resumeSession, refresh et flushOutbox afin que l'hôte puisse fournir une nouvelle tentative explicite après réception d'un token frais pour le même compte. Le code suivant utilise la forme du wrapper TypeScript (startSession(message, options) et sendMessage(text, idempotencyKey)). Dart utilise les mêmes opérations avec sendMessage(text, idempotencyKey: key). Les clients Swift et Kotlin directs utilisent leurs DTO de plateforme avec la même règle de clé stable, comme indiqué dans leurs références de plateforme.
const sessionKey = `order-${orderId}-session-${attemptId}`;
const messageKey = `order-${orderId}-question-${attemptId}`;
// Persist each key with its own user intent until the SDK acknowledges it.
await client.startSession("I need help with my order", {
idempotencyKey: sessionKey,
});
await client.sendMessage("The order number is ORD-42", messageKey);
// Call this only from an explicit "Retry the same message" control after
// connectivity and a fresh token for the same account are available.
async function retryPendingMessage() {
await client.resumeSession();
await client.flushOutbox();
}Distinguer les résultats en attente, refusés et dupliqués
Une erreur réseau ou de limitation peut rendre l'admission incertaine. Conservez donc la mutation originale pour une nouvelle tentative explicite avec la même clé. Les erreurs field-invalid, payload-too-large, message-rejected ou idempotency-conflict exigent une correction ou une investigation de l'hôte et ne doivent pas être rejouées automatiquement avec une autre clé.
Un résultat session-expired exige un nouveau token signé pour le même compte avant la nouvelle tentative. N'appelez pas resetSession pour une panne temporaire, car reset efface volontairement la session durable et les mutations en attente.
Rendre l'état hors ligne visible
- Affichez une étiquette d'attente ou de reconnexion liée à l'état de chargement du SDK et gardez le composer disponible uniquement lorsque l'hôte peut accepter une intention supplémentaire en sécurité.
- Proposez de renvoyer le même message après le rétablissement de la connectivité et de l'authentification. Gardez l'idempotency key originale derrière le contrôle et désactivez l'envoi dupliqué pendant son exécution.
- Si l'utilisateur abandonne volontairement la conversation, appelez resetSession et rendez le résultat explicite. N'effacez jamais l'état durable simplement parce que l'app est passée en arrière-plan.