Felo API PlatformFelo API Platform

Suporte

Triagem de um ticket de suporte em rascunho de resposta fundamentado

Masque o ticket, classifique intenção e prioridade com o Chat, recupere os trechos que respondem pela documentação, verifique conversas públicas de incidente e deixe um rascunho roteado para aprovação humana.

Tempo20 minutosNívelIntermediárioAtualizado2026-10-30
Para quemLíderes de suporteHelpdesk AgentEngenheiros de suporte

Copiar o prompt

Substitua os campos entre colchetes e cole no Claude Code, Codex ou qualquer IA com acesso ao terminal. Ela instala a skill da Felo, pergunta antes de gastar créditos e executa o fluxo.

Faça a triagem deste ticket de suporte e redija um rascunho de resposta para revisão humana: [cole o ticket depois de remover nome, e-mail, ID de conta, dados de pagamento e qualquer informação identificável].

Área de produto: [produto]. Plano ou região: [somente se necessário]. Fonte de documentação: [URL do central de ajuda ou LiveDoc short_id].
Caminho de aprovação: [quem revisa]. Fila de escalonamento: [equipe ou canal].

Produza:
1. Intenção: uma categoria e uma frase de justificativa.
2. Prioridade: urgente / normal / baixa, com a regra aplicada.
3. Evidência: os trechos de documentação que respondem ao ticket, com título e relevância.
4. Checagem de incidente: relatos públicos sugerem uma queda ampla? Link e data, ou “sem sinal público”.
5. Roteamento: rascunho, pedir informação ao cliente ou escalar — e por quê.
6. Rascunho de resposta: duas a quatro frases, apenas com a evidência, nomeando a fonte usada.

Regras:
- Não coloque nomes, e-mails, números de pedido, tokens ou dados de pagamento em chamadas de API nem em saídas. Trabalhe apenas com o ticket mascarado.
- Responda apenas com a documentação recuperada. Sem evidência, escale em vez de adivinhar.
- Não prometa reembolso, desconto, prazo ou mudança de conta; encaminhe esses casos para o escalonamento.
- Rumores públicos de queda são sinais, não provas. Cite o post e a data.
- Antes de gastar créditos, mostre as chamadas planejadas e aguarde minha aprovação.
- Não envie respostas, não atualize o ticket e não execute ações na conta. Devolva o rascunho para revisão.
- Grave o resultado em ./support-triage.md e resuma no chat.

A cópia também inclui os passos de instalação e as regras de segurança.

O que você recebe

Saída de exemplo de uma execução. Não é geração ao vivo.

Exemplo de triagem (trecho)

Triagem — ticket de exemplo

Intenção

Pergunta de cobrança / renovação. O cliente pergunta por que o plano renovou de novo.

Prioridade

Normal. É pergunta de cobrança, não queda, e o cliente não está bloqueado.

Evidência

  • “perguntas frequentes de cobrança” — momento da renovação e retries de cartão. Relevância: alta.
  • “Mudanças de plano” — downgrade entre renovações. Relevância: média.

Checagem de incidente

Sem relatos públicos nas últimas 48 horas.

Rota

Rascunho. A documentação cobre a pergunta.

Rascunho de resposta

Olá — seu plano renova no dia 1 de cada mês, e um cartão recusado é tentado por três dias antes de pausar a licença. Você pode trocar o cartão nas configurações de cobrança; a perguntas frequentes de cobrança tem o passo a passo. Se precisar mover a data de renovação, responda e escalaremos para o time de cobrança.

Nota para revisão

Aprovar, editar ou escalar para a fila de cobrança.

As chamadas exatas

Para desenvolvedores: o mesmo fluxo em código, na ordem de execução.

Mostrar as chamadas reais da API
  1. Masque e classifique

    Use código para remover e-mail, telefone e número de pedido e depois o Chat para intenção e prioridade.

    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);

    Saída de exemplo

    {
      "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": "…" }
      ]
    }
  2. Recupere evidências da documentação

    Busque trechos relevantes no LiveDoc da base de conhecimento, guardando títulos e pontuações.

    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");
    }

    Saída de exemplo

    [
      {
        "title": "Billing FAQ",
        "content": "Your plan renews on the first of the month; a failed card retries for three days…",
        "score": 0.91
      }
    ]
  3. Verifique incidente público

    Pesquise no X o produto e palavras como “falha/fora do ar” nas últimas 48 horas, só como sinal público.

    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,
    }));

    Saída de exemplo

    [
      {
        "text": "Workspace login is failing for my whole team.",
        "handle": "example_user",
        "at": "2026-10-30",
        "link": "https://x.com/example_user/status/..."
      }
    ]
  4. Defina a rota e monte a resposta

    As regras definem a fila; empacote evidências, próximo passo e rascunho de resposta.

    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);

    Saída de exemplo

    # 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)
  5. Registre a triagem

    Grave o resultado no LiveDoc para retrospectiva e auditoria.

    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 ticket

    Saída de exemplo

    { "short_id": "PvyKouzJirXjFdst4uKRK3" }

O que está incluído

  • Classificação de intenção e prioridade após mascaramento
  • Evidências da documentação com pontuações
  • Verificação de incidente público
  • Rascunho de resposta com roteamento
  • LiveDoc com o registro da triagem

O que não faz

  • Não envia resposta, não fecha ticket e não executa ações de conta
  • Não envie senhas, dados de pagamento ou dados completos do cliente à API
  • Sem resultado na documentação, o escalonamento é obrigatório
  • O X é sinal público de incidente, não o estado do sistema de suporte
  • As regras de prioridade são suas; o modelo apenas sugere

Perguntas

Que dados do ticket posso enviar?

Apenas o contexto necessário após mascarar: produto, descrição, plano e região. Não envie senhas, pagamento, endereço completo ou conversa privada.

De onde vem a resposta?

Dos trechos recuperados no LiveDoc de documentação. Sem resultado, o fluxo escala em vez de adivinhar.

Ele responde ou fecha o ticket?

Não. Ele só gera rascunho e rota; envio e fechamento ficam com uma pessoa ou seu sistema.

Como a prioridade é definida?

Pelas suas regras; o modelo sugere e justifica, e a rota confirma a prioridade final.

E quando a documentação não cobre?

Escalonamento para a fila humana, marcando “não coberto” no pacote de triagem.

Quanto custa uma triagem?

Chat, busca e X Search são cobrados por uso; as tarifas atuais estão na página de preços, e o prompt pede aprovação antes de gastar.

Fluxos relacionados

Faça do seu jeito

A mesma receita, adaptada ao seu processo real.

Só classificação

Sem resposta: apenas intenção, prioridade e fila sugerida.

Conecte ao sistema de tickets

Use seu webhook para gravar o pacote no ticket, sem envio automático.

Evolua para base de conhecimento

Quando houver resultado na documentação, passe ao fluxo de base de conhecimento para uma resposta mais completa.

As páginas de referência por trás desta receita e para onde ir depois.