客服
把客服工單分流成有依據的回覆草稿
先脫敏工單,用 Chat 判斷意圖和優先順序,從文件裡檢索能回答的段落,檢查是否有公開事故討論,再留下一份帶路由的回覆草稿給人工審批。
複製 prompt
把方括號裡的欄位替換掉,然後貼到 Claude Code、Codex 或任何能存取終端機的 AI。它會安裝 Felo skill、在花額度前詢問,並執行這套工作流程。
對這個支援工單做分診,並寫一份供人工審閱的回覆草稿:[貼上工單,先刪除姓名、電子郵件、帳號 ID、支付資料和其他可識別資訊]。 產品領域:[產品]。方案或地區:[僅在回答需要時]。文件來源:[幫助中心 URL 或 LiveDoc short_id]。 核准路徑:[誰審閱]。升級佇列:[團隊或頻道]。 輸出: 1. 意圖:一個類別,加一句理由。 2. 優先級:緊急 / 一般 / 低,附適用規則。 3. 依據:能回答工單的文件段落,附標題和相關度。 4. 故障檢查:公開報告是否暗示大範圍故障。附連結和日期,或寫「無公開訊號」。 5. 路由:起草回覆、向客戶補資料,或升級——並說明原因。 6. 回覆草稿:兩到四句,只基於證據,並點名所依據的來源。 規則: - 不要把姓名、電子郵件、訂單號、權杖或支付資料放進 API 呼叫或輸出。只處理已去識別化的工單。 - 只根據檢索到的文件回答。沒有依據時升級,不要猜測。 - 不要承諾退款、折扣、時限或帳戶變更;這些轉給升級流程。 - 公開故障傳聞是訊號,不是證據。引用貼文和日期。 - 消耗額度前,先展示預計執行的呼叫並等待我批准。 - 不要傳送回覆、更新工單或操作帳戶。把草稿回傳給我審閱。 - 將結果寫入 ./support-triage.md,並在對話中總結。
複製的內容也包含安裝步驟和安全規則。
你會得到什麼
一次執行的範例輸出,不是即時生成。
分診 — 範例工單
意圖
帳單 / 續約問題。客戶詢問為什麼方案又續約了。
優先級
一般。這是帳單問題,不是故障,客戶沒有被阻擋。
依據
- 「帳單常見問題」 — 續約時間與扣款失敗重試。相關度:高。
- 「方案變更」 — 續約之間的降級。相關度:中。
故障檢查
過去 48 小時沒有公開報告。
路由
起草回覆。文件涵蓋了這個問題。
回覆草稿
你好——你的方案在每月 1 日續約,信用卡扣款失敗後會重試三天,然後席位暫停。你可以在帳單設定中更換信用卡;帳單常見問題 有逐步說明。如果需要更改續約日期,請回覆,我們會升級給帳單團隊。
審核備註
批准、編輯,或升級到帳單佇列。
實際呼叫
給開發者:同一套工作流程的可複製程式碼,依執行順序排列。
展開實際 API 呼叫
脫敏後再分類
用程式碼去掉電子郵件、電話、訂單號等 PII,再用 Chat 判斷意圖和優先順序。
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);範例輸出
{ "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": "…" } ] }檢索文件證據
從客服知識庫 LiveDoc 檢索相關段落,保留標題和分數。
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"); }範例輸出
[ { "title": "Billing FAQ", "content": "Your plan renews on the first of the month; a failed card retries for three days…", "score": 0.91 } ]檢查公開事故
在 X 搜產品名和「故障/中斷」等詞,限定 48 小時,只作為公開訊號。
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, }));範例輸出
[ { "text": "Workspace login is failing for my whole team.", "handle": "example_user", "at": "2026-10-30", "link": "https://x.com/example_user/status/..." } ]定路由並組裝回覆
依規則決定佇列,把證據、下一步和回覆草稿打包。
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);範例輸出
# 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)
記錄分流
把分流結果寫進 LiveDoc,方便復盤和稽核。
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範例輸出
{ "short_id": "PvyKouzJirXjFdst4uKRK3" }
包含什麼
- 脫敏後的意圖和優先順序分類
- 帶分數的文件證據
- 公開事故檢查結果
- 帶路由的回覆草稿
- 分流記錄 LiveDoc
不做什麼
- 不發送回覆、不關閉工單、不做帳戶操作
- 不要把密碼、付款資訊或完整客戶資料發給 API
- 沒有文件命中時必須升級
- X 只用於公開事故訊號,不代表客服系統狀態
- 優先順序規則由你定義,模型只給建議
常見問題
可以發送哪些工單資料?
只發送脫敏後的產品、問題描述、方案和地區等必要上下文。不要發送密碼、付款資訊、完整地址或私人對話。
回覆從哪裡來?
來自你的文件 LiveDoc 檢索出的段落。沒有命中時工作流程會升級,而不是猜。
它會直接回覆或關閉工單嗎?
不會。它只生成草稿和路由,發送和關閉必須由人工或你的系統完成。
優先順序怎麼定?
由你定義的規則決定;模型給出建議和理由,最終優先順序由路由規則確認。
文件沒有涵蓋時怎麼辦?
升級到人工佇列,並在分流包裡註明「未涵蓋」。
一次分流要花多少?
Chat、檢索和 X 搜尋按用量計費;目前費率在價格頁面,prompt 會先請求確認。
相關工作流程
改成你的版本
同一套配方,依你實際的交付方式調整。
只做分類
不生成回覆,只輸出意圖、優先順序和建議佇列。
接入工單系統
透過你自己的 webhook 把分流包寫進工單,不自動發送。
升級為知識庫回答
文件命中時,交給客服知識庫工作流程生成更完整的回答。
繼續深入
這套配方背後的參考頁面,以及下一步可以看什麼。