Support
Transformez un ticket support en brouillon de réponse fondé
Masquez le ticket, classez intention et priorité avec Chat, récupérez les passages qui répondent dans la documentation, vérifiez les incidents publics et laissez un brouillon routé à approuver par un humain.
Copier le prompt
Remplacez les champs entre crochets, puis collez dans Claude Code, Codex ou toute IA avec accès au terminal. Elle installe le skill Felo, demande avant de dépenser des crédits et exécute le workflow.
Triage ce ticket de support et rédige un brouillon de réponse pour relecture humaine : [colle le ticket après avoir retiré nom, e-mail, ID de compte, données de paiement et toute information identifiante]. Domaine produit : [produit]. Offre ou région : [seulement si nécessaire]. Source documentaire : [URL du centre d’aide ou LiveDoc short_id]. Voie d’approbation : [qui relit]. File d’escalade : [équipe ou canal]. Produis : 1. Intention : une catégorie et une phrase de justification. 2. Priorité : urgente / normale / basse, avec la règle appliquée. 3. Preuves : les passages de documentation qui répondent au ticket, avec titre et pertinence. 4. Vérification d’incident : les rapports publics suggèrent-ils une panne large ? Lien et date, ou « aucun signal public ». 5. Routage : brouillon, demande d’informations au client ou escalade — et pourquoi. 6. Brouillon de réponse : deux à quatre phrases, fondées uniquement sur les preuves, en nommant la source utilisée. Règles : - Ne mets aucun nom, e-mail, numéro de commande, token ou donnée de paiement dans les appels API ou les sorties. Travaille uniquement sur le ticket masqué. - Réponds uniquement à partir de la documentation récupérée. Sans preuve, escalade au lieu de deviner. - Ne promets ni remboursement, ni remise, ni délai, ni modification de compte ; renvoie ces cas à l’escalade. - Les rumeurs publiques de panne sont des signaux, pas des preuves. Cite la publication et la date. - Avant de consommer des crédits, montre les appels prévus et attends mon accord. - N’envoie pas de réponse, ne mets pas à jour le ticket et n’effectue aucune action sur le compte. Rends le brouillon pour relecture. - Écris le résultat dans ./support-triage.md et résume-le dans le chat.
La copie inclut aussi les étapes d'installation et les règles de sécurité.
Ce que vous obtenez
Exemple de sortie d'une exécution. Pas de génération en direct.
Triage — ticket d’exemple
Intention
Question facturation / renouvellement. Le client demande pourquoi l’offre a été renouvelée à nouveau.
Priorité
Normale. C’est une question de facturation, pas une panne, et le client n’est pas bloqué.
Preuves
- « questions fréquentes de facturation » — date de renouvellement et retries de carte refusée. Pertinence : élevée.
- « Changements d’offre » — downgrade entre deux renouvellements. Pertinence : moyenne.
Vérification d’incident
Aucun rapport public ces 48 dernières heures.
Routage
Brouillon. La documentation couvre la question.
Brouillon de réponse
Bonjour — votre offre se renouvelle le premier du mois, et une carte refusée est retentée pendant trois jours avant la suspension du siège. Vous pouvez changer la carte dans les paramètres de facturation ; la questions fréquentes de facturation donne les étapes. Si la date de renouvellement doit être déplacée, répondez et nous escaladerons à l’équipe facturation.
Note pour le relecteur
Approuver, modifier ou escalader vers la file facturation.
Les appels exacts
Pour les développeurs : le même workflow en code, dans l'ordre d'exécution.
Afficher les appels API
Masquez puis classez
Retirez par code e-mail, téléphone et numéro de commande, puis utilisez Chat pour intention et priorité.
triage.ts const BASE = "https://openapi.felo.ai"; const headers = { Authorization: `Bearer ${process.env.FELO_API_KEY}`, "Content-Type": "application/json", }; async function felo<T>(path: string, body?: unknown): Promise<T> { const res = await fetch(`${BASE}${path}`, { method: body ? "POST" : "GET", headers, body: body ? JSON.stringify(body) : undefined, }); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); return res.json() as Promise<T>; } const redact = (text: string) => text .replace(/[\w.+-]+@[\w.-]+\.\w+/g, "[email]") .replace(/\b(?:acct|account|order|invoice)[-_ ]?\w+\b/gi, "[id]") .replace(/\b(?:\d[ -]?){13,19}\b/g, "[card]"); type Ticket = { id: string; product: string; subject: string; body: string; plan?: string; sensitive?: boolean; }; const ticket: Ticket = { id: "T-1042", product: "Acme Workspace", subject: "Why did my plan renew?", body: "I was charged again and cannot find the renewal date on my account.", plan: "team", }; const summary = redact(`${ticket.subject}\n\n${ticket.body}`).slice(0, 1500); type ChatData = { data: { answer: string; resources: { link: string; title: string; snippet: string }[]; }; }; const triage = await felo<ChatData>("/v2/chat", { query: `Classify this support question by intent and priority, and list what is missing:\n\n${summary}`, }); console.log(triage.data.answer);Exemple de sortie
{ "answer": "Intent: billing / renewal question. Priority: normal. Missing: the renewal date the customer expects.", "resources": [ { "link": "https://example.com/billing-faq", "title": "Billing FAQ", "snippet": "…" } ] }Récupérez les preuves documentaires
Cherchez les passages pertinents dans le LiveDoc de la base de connaissances, en gardant titres et scores.
triage.ts type Hit = { title: string; content: string; score: number }; const KB = process.env.SUPPORT_LIVEDOC_ID!; // the help-center LiveDoc short_id const retrieved = await felo<{ data: Hit[] }>( `/v2/livedocs/${KB}/resources/retrieve`, { query: summary }, ); const hits = retrieved.data.filter((hit) => hit.score >= 0.7).slice(0, 4); if (hits.length === 0) { console.log("No grounded evidence: escalate instead of drafting"); }Exemple de sortie
[ { "title": "Billing FAQ", "content": "Your plan renews on the first of the month; a failed card retries for three days…", "score": 0.91 } ]Vérifiez l’incident public
Cherchez sur X le produit et des mots comme « panne/indisponible » sur 48 heures, uniquement comme signal public.
triage.ts type XData = { data: { tweets: { content: string; author: { username: string }; created_at: string; url: string; }[]; }; }; const since = Math.floor((Date.now() - 48 * 60 * 60 * 1000) / 1000); const incident = await felo<XData>("/v2/x/tweet/search", { query: `"${ticket.product}" (outage OR "not working" OR error)`, limit: 20, since_time: since, }); const reports = incident.data.tweets.map((post) => ({ text: post.content, handle: post.author.username, at: post.created_at.slice(0, 10), link: post.url, }));Exemple de sortie
[ { "text": "Workspace login is failing for my whole team.", "handle": "example_user", "at": "2026-10-30", "link": "https://x.com/example_user/status/..." } ]Définissez la route et assemblez la réponse
Les règles décident la file ; rassemblez preuves, prochaine étape et brouillon.
triage.ts type Route = "draft" | "ask-customer" | "escalate"; function decideRoute(): { route: Route; reason: string } { if (hits.length === 0) { return { route: "escalate", reason: "no grounded evidence in the knowledge base" }; } if (ticket.sensitive) { return { route: "escalate", reason: "an account or billing action is requested" }; } if (reports.length >= 3) { return { route: "escalate", reason: "public reports suggest a wider issue" }; } if (!ticket.plan) { return { route: "ask-customer", reason: "the plan is needed to answer the question" }; } return { route: "draft", reason: "the documentation covers the question" }; } const decision = decideRoute(); const packet = [ `# Triage — ${ticket.id}`, "", `Route: ${decision.route} (${decision.reason})`, "", "## Intent and priority", triage.data.answer, "", "## Evidence", ...hits.map((hit) => `- ${hit.title} (score ${hit.score})`), "", "## Public signal", ...(reports.length ? reports.map((report) => `- @${report.handle} (${report.at}): ${report.text} — ${report.link}`) : ["No public reports in the last 48 hours."]), "", "## Reply draft", "[Written by the host Agent from the evidence above — human review required]", ].join("\n"); console.log(packet);Exemple de sortie
# Triage — T-1042 Route: draft (the documentation covers the question) ## Intent and priority Intent: billing / renewal question. Priority: normal. ## Evidence - Billing FAQ (score 0.91)
Consignez le triage
Écrivez le résultat dans le LiveDoc pour la rétrospective et l’audit.
triage.ts type LiveDocData = { data: { short_id: string } }; const log = await felo<LiveDocData>("/v2/livedocs", { name: "Support triage log", description: "One document resource per triaged ticket", }); await felo(`/v2/livedocs/${log.data.short_id}/resources/doc`, { title: `Triage — ${ticket.id}`, content: packet, }); console.log(log.data.short_id); // reuse it for the next ticketExemple de sortie
{ "short_id": "PvyKouzJirXjFdst4uKRK3" }
Ce qui est inclus
- Intention et priorité après masquage
- Preuves documentaires avec scores
- Vérification d’incident public
- Brouillon de réponse routé
- LiveDoc avec le journal de triage
Ce qu'elle ne fait pas
- N’envoie pas de réponse, ne ferme pas le ticket et n’exécute pas d’action de compte
- N’envoyez pas mots de passe, données de paiement ou données client complètes à l’API
- Sans résultat documentaire, l’escalade est obligatoire
- X est un signal d’incident public, pas l’état du système support
- Les règles de priorité sont les vôtres ; le modèle ne fait que proposer
Questions
Quelles données de ticket puis-je envoyer ?
Seulement le contexte nécessaire après masquage : produit, description, offre et région. Pas de mots de passe, paiement, adresse complète ni conversation privée.
D’où vient la réponse ?
Des passages récupérés dans le LiveDoc de documentation. Sans résultat, le workflow escalade au lieu de deviner.
Répond-il ou ferme-t-il le ticket ?
Non. Il produit seulement brouillon et route ; envoi et fermeture sont faits par un humain ou votre système.
Comment la priorité est-elle décidée ?
Par vos règles ; le modèle propose et justifie, la route confirme la priorité finale.
Et si la documentation ne couvre pas ?
Escalade vers la file humaine, avec « non couvert » dans le paquet de triage.
Combien coûte un triage ?
Chat, recherche et X Search sont facturés à l’usage ; les tarifs actuels sont sur la page des prix, et le prompt demande votre accord avant dépense.
Workflows liés
Répondez aux questions support depuis votre propre documentation
Créez un LiveDoc, chargez le centre d’aide et le runbook interne, récupérez les passages qui répondent au ticket et laissez le modèle répondre uniquement à partir de ces preuves.
Ouvrir le workflowContenuTransformez les conversations sociales en brief d’écoute hebdomadaire
Cherchez les posts X de la semaine sur votre marque et vos concurrents, ajoutez un contexte web sourcé, lisez les pages derrière et archivez chaque édition pour que la semaine suivante parte du connu.
Ouvrir le workflowRechercheTransformez une question en brief de recherche sourcé
Interrogez le web, récupérez les pages derrière la réponse en Markdown, ajoutez ce que disent les praticiens sur X, puis conservez les preuves dans un LiveDoc que vous pourrez interroger plus tard.
Ouvrir le workflowAdaptez-la
La même recette, adaptée à votre façon de livrer.
Classification seule
Sans réponse : seulement intention, priorité et file recommandée.
Connectez au système de tickets
Avec votre webhook, écrivez le paquet dans le ticket sans envoi automatique.
Passez à la base de connaissances
En cas de résultat documentaire, passez au workflow de base de connaissances pour une réponse plus complète.
Aller plus loin
Les pages de référence derrière cette recette et la suite.