Soporte
Clasifica un ticket de soporte en un borrador de respuesta fundamentado
Enmascara el ticket, clasifica intención y prioridad con Chat, recupera los pasajes que responden desde la documentación, revisa conversaciones públicas de incidencia y deja un borrador enrutado para aprobación humana.
Copiar el prompt
Sustituye los campos entre corchetes y pégalo en Claude Code, Codex o cualquier IA con acceso a terminal. Instala el skill de Felo, pregunta antes de gastar créditos y ejecuta el flujo.
Clasifica este ticket de soporte y redacta un borrador de respuesta para revisión humana: [pega el ticket después de quitar nombre, correo, ID de cuenta, datos de pago y cualquier información identificable]. Área de producto: [producto]. Plan o región: [solo si hace falta para responder]. Fuente documental: [URL del centro de ayuda o LiveDoc short_id]. Ruta de aprobación: [quién revisa]. Cola de escalado: [equipo o canal]. Genera: 1. Intención: una categoría y una frase de justificación. 2. Prioridad: urgente / normal / baja, con la regla aplicada. 3. Evidencia: los pasajes de documentación que responden al ticket, con título y relevancia. 4. Comprobación de incidentes: ¿los informes públicos sugieren una caída amplia? Enlace y fecha, o «sin señal pública». 5. Enrutado: borrador, pedir información al cliente o escalar, y por qué. 6. Borrador de respuesta: de dos a cuatro frases, solo con la evidencia, nombrando la fuente en la que se apoya. Reglas: - No incluyas nombres, correos, números de pedido, tokens ni datos de pago en llamadas API ni salidas. Trabaja solo con el ticket enmascarado. - Responde solo con la documentación recuperada. Sin evidencia, escala en lugar de adivinar. - No prometas reembolsos, descuentos, plazos ni cambios de cuenta; deriva esos casos al escalado. - Los rumores públicos de caída son señales, no pruebas. Cita la publicación y la fecha. - Antes de gastar créditos, muestra las llamadas previstas y espera mi aprobación. - No envíes respuestas, no actualices el ticket ni actúes sobre la cuenta. Devuelve el borrador para revisión. - Escribe el resultado en ./support-triage.md y resúmelo en el chat.
La copia también incluye los pasos de instalación y las reglas de seguridad.
Lo que obtienes
Salida de ejemplo de una ejecución. No es generación en vivo.
Triaje — ticket de ejemplo
Intención
Pregunta de facturación / renovación. El cliente pregunta por qué se renovó el plan otra vez.
Prioridad
Normal. Es una pregunta de facturación, no una caída, y el cliente no está bloqueado.
Evidencia
- «preguntas frecuentes de facturación» — momento de renovación y reintentos de tarjeta. Relevancia: alta.
- «Cambios de plan» — downgrade entre renovaciones. Relevancia: media.
Comprobación de incidentes
Sin reportes públicos en las últimas 48 horas.
Ruta
Borrador. La documentación cubre la pregunta.
Borrador de respuesta
Hola: tu plan se renueva el día 1 de cada mes, y una tarjeta fallida se reintenta durante tres días antes de pausar el asiento. Puedes cambiar la tarjeta en Ajustes de facturación; la preguntas frecuentes de facturación tiene los pasos. Si necesitas mover la fecha de renovación, responde y lo escalaremos al equipo de facturación.
Nota para revisión
Aprobar, editar o escalar a la cola de facturación.
Las llamadas exactas
Para desarrolladores: el mismo flujo como código, en orden de ejecución.
Mostrar las llamadas reales a la API
Enmascara y clasifica
Retira por código email, teléfono y número de pedido, y luego usa Chat para intención y prioridad.
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);Salida de ejemplo
{ "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": "…" } ] }Recupera evidencias documentales
Busca pasajes relevantes en el LiveDoc de la base de conocimiento, guardando títulos y puntuaciones.
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"); }Salida de ejemplo
[ { "title": "Billing FAQ", "content": "Your plan renews on the first of the month; a failed card retries for three days…", "score": 0.91 } ]Comprueba incidencia pública
Busca en X el producto y palabras como «caída/indisponible» en 48 horas, solo como señal pública.
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, }));Salida de ejemplo
[ { "text": "Workspace login is failing for my whole team.", "handle": "example_user", "at": "2026-10-30", "link": "https://x.com/example_user/status/..." } ]Define la ruta y monta la respuesta
Las reglas deciden la cola; empaqueta evidencias, siguiente paso y borrador.
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);Salida de ejemplo
# 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)
Registra el triaje
Escribe el resultado en el LiveDoc para retrospectiva y auditoría.
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 ticketSalida de ejemplo
{ "short_id": "PvyKouzJirXjFdst4uKRK3" }
Qué incluye
- Clasificación de intención y prioridad tras enmascarar
- Evidencias documentales con puntuaciones
- Comprobación de incidencia pública
- Borrador de respuesta enrutado
- LiveDoc con el registro de triaje
Qué no hace
- No envía respuesta, no cierra el ticket ni ejecuta acciones de cuenta
- No envíes contraseñas, datos de pago ni datos completos del cliente a la API
- Sin resultado documental, el escalado es obligatorio
- X es una señal pública de incidencia, no el estado del sistema de soporte
- Las reglas de prioridad son tuyas; el modelo solo sugiere
Preguntas
¿Qué datos del ticket puedo enviar?
Solo el contexto necesario tras enmascarar: producto, descripción, plan y región. No envíes contraseñas, pago, dirección completa ni conversación privada.
¿De dónde viene la respuesta?
De los pasajes recuperados del LiveDoc de documentación. Sin resultados, el flujo escala en vez de adivinar.
¿Responde o cierra el ticket?
No. Solo genera borrador y ruta; envío y cierre los hace una persona o tu sistema.
¿Cómo se decide la prioridad?
Con tus reglas; el modelo sugiere y justifica, y la ruta confirma la prioridad final.
¿Y si la documentación no cubre?
Escalado a la cola humana, marcando «no cubierto» en el paquete de triaje.
¿Cuánto cuesta un triaje?
Chat, búsqueda y X Search se facturan por uso; las tarifas están en la página de precios y el prompt pide aprobación antes de gastar.
Flujos relacionados
Responde preguntas de soporte desde tu propia documentación
Crea un LiveDoc, carga el centro de ayuda y el runbook interno, recupera los pasajes que responden al ticket y deja que el modelo responda solo con esas evidencias.
Abrir el flujo de trabajoContenidoConvierte las conversaciones sociales en un brief semanal de escucha
Busca los posts de X de la última semana sobre tu marca y competidores, añade contexto web con fuentes, lee las páginas detrás y archiva cada edición para que la siguiente semana empiece por lo conocido.
Abrir el flujo de trabajoInvestigaciónConvierte una pregunta en un brief de investigación con fuentes
Pregunta a la web, guarda las páginas detrás de la respuesta como Markdown, añade lo que dicen los profesionales en X y conserva las evidencias en un LiveDoc que puedes consultar después.
Abrir el flujo de trabajoHazlo tuyo
La misma receta, adaptada a cómo entregas de verdad.
Solo clasificación
Sin respuesta: solo intención, prioridad y cola recomendada.
Conecta al sistema de tickets
Con tu webhook, escribe el paquete en el ticket sin envío automático.
Pasa a base de conocimiento
Con resultado documental, pasa al flujo de base de conocimiento para una respuesta más completa.
Seguir
Las páginas de referencia detrás de esta receta y los siguientes pasos.