Felo API PlatformFelo API Platform

Support

Ein Support-Ticket in einen belegten Antwortentwurf triagieren

Maskiere das Ticket, klassifiziere Absicht und Priorität mit Chat, rufe die antwortenden Passagen aus der Dokumentation ab, prüfe öffentliche Incident-Gespräche und hinterlasse einen gerouteten Antwortentwurf zur menschlichen Freigabe.

Dauer20 MinutenLevelFortgeschrittenAktualisiert2026-10-30
Für wenSupport-LeadsHelpdesk-AgentSupport-Engineers

Prompt kopieren

Ersetze die Felder in eckigen Klammern und füge den Prompt in Claude Code, Codex oder eine KI mit Terminalzugriff ein. Sie installiert den Felo-Skill, fragt vor Credits und führt den Workflow aus.

Triage dieses Support-Ticket und erstelle einen Antwortentwurf zur menschlichen Prüfung: [Ticket einfügen, nachdem Name, E-Mail, Konto-ID, Zahlungsdaten und andere identifizierende Informationen entfernt wurden].

Produktbereich: [Produkt]. Plan oder Region: [nur wenn für die Antwort nötig]. Dokumentationsquelle: [Help-Center-URL oder LiveDoc short_id].
Freigabeweg: [wer prüft]. Eskalations-Queue: [Team oder Kanal].

Erstelle:
1. Absicht: eine Kategorie und eine Begründung in einem Satz.
2. Priorität: dringend / normal / niedrig, mit der angewandten Regel.
3. Belege: die Dokumentationsstellen, die das Ticket beantworten, mit Titel und Relevanz.
4. Incident-Check: ob öffentliche Berichte auf eine breite Störung hindeuten. Link und Datum oder „kein öffentliches Signal“.
5. Routing: Entwurf, Rückfrage beim Kunden oder Eskalation — und warum.
6. Antwortentwurf: zwei bis vier Sätze, ausschließlich auf den Belegen basierend, mit Nennung der Quelle.

Regeln:
- Setze keine Namen, E-Mails, Bestellnummern, Tokens oder Zahlungsdaten in API-Aufrufe oder Ausgaben. Arbeite nur mit dem maskierten Ticket.
- Antworte nur aus der abgerufenen Dokumentation. Ohne Beleg eskalieren, nicht raten.
- Verspreche keine Rückerstattungen, Rabatte, Fristen oder Kontänderungen; verweise dafür an die Eskalation.
- Öffentliche Störungsgerüchte sind Signale, keine Beweise. Zitiere Beitrag und Datum.
- Bevor Credits verbraucht werden, zeige die geplanten Aufrufe und warte auf meine Freigabe.
- Sende keine Antwort, aktualisiere kein Ticket und führe keine Kontomaßnahmen aus. Gib den Entwurf zur Prüfung zurück.
- Schreibe das Ergebnis nach ./support-triage.md und fasse es im Chat zusammen.

Die Kopie enthält auch die Installationsschritte und Sicherheitsregeln.

Das bekommst du

Beispielausgabe eines Laufs. Keine Live-Generierung.

Beispiel-Triage (Auszug)

Triage — Beispiel-Ticket

Absicht

Abrechnungs-/Verlängerungsfrage. Der Kunde fragt, warum der Plan erneut verlängert wurde.

Priorität

Normal. Es ist eine Abrechnungsfrage, kein Ausfall, und der Kunde ist nicht blockiert.

Evidenz

  • „Häufige Fragen zur Abrechnung“ — Verlängerungszeitpunkt und Retries bei fehlgeschlagener Karte. Relevanz: hoch.
  • „Planänderungen“ — Downgrade zwischen Verlängerungen. Relevanz: mittel.

Incident-Check

Keine öffentlichen Meldungen in den letzten 48 Stunden.

Route

Entwurf. Die Dokumentation deckt die Frage ab.

Antwortentwurf

Hallo — dein Plan verlängert sich am Ersten des Monats, und eine fehlgeschlagene Karte wird drei Tage lang erneut versucht, bevor der Seat pausiert wird. Du kannst die Karte in den Billing-Einstellungen ändern; die Häufige Fragen zur Abrechnung hat die Schritte. Wenn das Verlängerungsdatum verschoben werden soll, antworte, und wir eskalieren an das Billing-Team.

Prüfernotiz

Freigeben, bearbeiten oder an die Billing-Queue eskalieren.

Die konkreten Aufrufe

Für Entwickler: derselbe Workflow als kopierbarer Code in Ausführungsreihenfolge.

Konkrete API-Aufrufe zeigen
  1. Maskieren und klassifizieren

    Entferne per Code E-Mail, Telefon und Bestellnummern und bestimme dann mit Chat Absicht und Priorität.

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

    Beispielausgabe

    {
      "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. Dokumentationsbelege suchen

    Suche im Support-LiveDoc nach relevanten Passagen und behalte Titel und 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");
    }

    Beispielausgabe

    [
      {
        "title": "Billing FAQ",
        "content": "Your plan renews on the first of the month; a failed card retries for three days…",
        "score": 0.91
      }
    ]
  3. Öffentlichen Incident prüfen

    Suche auf X nach Produkt und Wörtern wie „Störung/Ausfall“ in den letzten 48 Stunden, nur als öffentliches Signal.

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

    Beispielausgabe

    [
      {
        "text": "Workspace login is failing for my whole team.",
        "handle": "example_user",
        "at": "2026-10-30",
        "link": "https://x.com/example_user/status/..."
      }
    ]
  4. Route bestimmen und Antwort bauen

    Regeln bestimmen die Warteschlange; packe Belege, nächsten Schritt und Antwortentwurf zusammen.

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

    Beispielausgabe

    # 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. Triage aufzeichnen

    Schreibe das Ergebnis ins LiveDoc für Rückblick und 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 ticket

    Beispielausgabe

    { "short_id": "PvyKouzJirXjFdst4uKRK3" }

Enthalten

  • Absicht und Priorität nach der Maskierung
  • Dokumentationsbelege mit Scores
  • Prüfung auf öffentliche Incidents
  • Gerouteter Antwortentwurf
  • LiveDoc mit der Triage-Aufzeichnung

Was es nicht macht

  • Sendet keine Antwort, schließt kein Ticket und führt keine Kontomaßnahmen aus
  • Keine Passwörter, Zahlungsdaten oder vollständigen Kundendaten an die API
  • Ohne Dokumentationstreffer ist die Eskalation Pflicht
  • X ist ein öffentliches Incident-Signal, kein Status des Supportsystems
  • Prioritätsregeln definierst du; das Modell schlägt nur vor

Fragen

Welche Ticketdaten darf ich senden?

Nur den nötigen maskierten Kontext: Produkt, Problembeschreibung, Plan und Region. Keine Passwörter, Zahlungsdaten, vollständige Adressen oder private Gespräche.

Woher kommt die Antwort?

Aus den im LiveDoc gefundenen Dokumentationspassagen. Ohne Treffer eskaliert der Workflow, statt zu raten.

Antwortet oder schließt es das Ticket?

Nein. Es erstellt nur Entwurf und Route; Versand und Schließen übernimmt ein Mensch oder dein System.

Wie wird die Priorität bestimmt?

Durch deine Regeln; das Modell schlägt vor und begründet, die Route bestätigt die endgültige Priorität.

Was, wenn die Dokumentation nicht abdeckt?

Eskalation an die menschliche Warteschlange mit „nicht abgedeckt“ im Triage-Paket.

Was kostet eine Triage?

Chat, Suche und X Search werden nutzungsbasiert abgerechnet; aktuelle Preise stehen auf der Preisseite, und der Prompt fragt vor Ausgaben nach Bestätigung.

Verwandte Workflows

Mach es zu deinem

Dasselbe Rezept, angepasst an deinen tatsächlichen Ablauf.

Nur Klassifikation

Ohne Antwort: nur Absicht, Priorität und empfohlene Warteschlange.

Ticket-System anbinden

Schreibe das Paket per eigenem Webhook ins Ticket, ohne automatischen Versand.

Zur Wissensbasis ausbauen

Bei Dokumentationstreffern an den Wissensbasis-Workflow für eine vollständigere Antwort übergeben.

Die Referenzseiten hinter diesem Rezept und die nächsten Schritte.