客服
用你自己的文件回答客服問題
建立一個 LiveDoc,匯入幫助中心和內部 runbook,檢索能回答工單的段落,再讓模型只根據這些證據回答。
複製 prompt
把方括號裡的欄位替換掉,然後貼到 Claude Code、Codex 或任何能存取終端機的 AI。它會安裝 Felo skill、在花額度前詢問,並執行這套工作流程。
只用我們的文件回答這個支援問題:[客戶問題]。 知識庫:[幫助中心 URL 或 LiveDoc short_id]。升級路徑:[負責人或佇列]。 可用客戶脈絡:[方案、地區、產品](不要索取密碼或支付資料)。 輸出: 1. 兩到四句直接回答。 2. 支撐回答的文件段落,附資源標題。 3. 客戶的下一步。 4. 內部備註:使用的資源和相關度分數。 規則: - 只根據檢索到的段落回答。沒有命中或相關度低時升級,絕不猜測。 - 不要編造政策、退款、定價或帳戶操作。 - 不要引入客戶私密資料、憑證或支付資訊。 - 在消耗額度做資料匯入或檢索前先詢問。 - 不要把回答傳送給客戶;回傳給我審閱。
複製的內容也包含安裝步驟和安全規則。
你會得到什麼
一次執行的範例輸出,不是即時生成。
回答:你的方案在每月 1 日續約。信用卡扣款失敗後會重試三天,然後席位暫停。
來源:「帳單常見問題」 - https://example.com/help/billing
如果這裡沒有涵蓋:帶上發票 ID 升級到帳單佇列。
實際呼叫
給開發者:同一套工作流程的可複製程式碼,依執行順序排列。
展開實際 API 呼叫
建立知識庫
用 LiveDoc API 建立一個知識庫,保存 short_id。
support.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>; } type LiveDocData = { data: { short_id: string } }; const kb = await felo<LiveDocData>("/v2/livedocs", { name: "Support knowledge base", description: "Help center, policy pages, and internal runbooks", }); const kbId = kb.data.short_id; // save this in your config範例輸出
{ "short_id": "PvyKouzJirXjFdst4uKRK3", "name": "Support knowledge base", "description": "Help center, policy pages, and internal runbooks" }匯入公開幫助中心
把幫助中心 URL 作為資源加進 LiveDoc。
support.ts type UrlResult = { data: { url: string; status: string; fail_reason: string | null; resource_id: string | null; }[]; }; const added = await felo<UrlResult>( `/v2/livedocs/${kbId}/resources/urls`, { urls: [ "https://example.com/help/getting-started", { url: "https://example.com/help/billing", title: "Billing FAQ" }, ], }, ); const failed = added.data.filter((item) => item.status === "failed");範例輸出
[ { "url": "https://example.com/help/getting-started", "status": "success", "resource_id": "res_003" }, { "url": "https://example.com/help/billing", "status": "existed", "resource_id": "res_004" } ]補充非公開文件
把內部 runbook 作為文件資源加進去。
support.ts type ResourceData = { data: { id: string } }; const runbook = `# Refund policy Refunds are available within 30 days of purchase. Requests after 30 days need a manual review by the billing team. `; const policy = await felo<ResourceData>( `/v2/livedocs/${kbId}/resources/doc`, { title: "Refund policy", content: runbook }, ); console.log(policy.data.id); // use this for updates檢索問題相關證據
用語意檢索拿到最相關的段落和分數。
support.ts type Hit = { id: string; title: string; content: string; score: number }; async function findEvidence(question: string) { const res = await felo<{ data: Hit[] }>( `/v2/livedocs/${kbId}/resources/retrieve`, { query: question }, ); return res.data.filter((hit) => hit.score >= 0.7).slice(0, 4); } const question = "Can I get a refund after 45 days?"; const hits = await findEvidence(question);範例輸出
[ { "id": "res_005", "title": "Refund policy", "content": "Refunds are available within 30 days of purchase…", "score": 0.92 } ]只基於證據回答
讓模型只使用檢索到的段落,並在沒有命中時升級。
support.ts type Completion = { choices: { message: { content: string | null } }[]; usage: { prompt_tokens: number; completion_tokens: number; total_tokens: number }; }; const context = hits .map((hit) => `### ${hit.title}\n${hit.content}`) .join("\n\n"); const completion = await felo<Completion>("/api/v1/chat/completions", { model: "anthropic/claude-haiku-5.5", messages: [ { role: "system", content: "Answer only from the context. If the context does not cover the question, say so and hand the ticket to a human.", }, { role: "user", content: `Context:\n${context}\n\nQuestion: ${question}`, }, ], }); console.log(completion.choices[0].message.content); console.log(completion.usage.total_tokens);範例輸出
"No. The Refund policy says refunds are available within 30 days of purchase, so a request at 45 days needs a manual review by the billing team."
包含什麼
- 由幫助中心和內部 runbook 建立的 LiveDoc
- 帶段落和標題的語意檢索
- 有依據、可引用的回答
- 文件不涵蓋時明確的升級路徑
不做什麼
- 只從你的文件回答,不瀏覽開放網路
- 不執行帳戶操作、退款或改方案
- 不能把私有客戶資料或憑證放進知識庫
- 文件過時會導致回答過時,需要定期更新
- 它只起草回答,不直接發給客戶
常見問題
回答從哪裡來?
只來自你建立的 LiveDoc:幫助中心頁面和 runbook。檢索回傳段落,agent 再基於段落寫回答。
文件沒有涵蓋時怎麼辦?
升級。沒有命中或相關度過低就視為未涵蓋,而不是允許模型猜。
怎麼保持知識庫最新?
政策變化時重新加入或更新 URL 和文件資源;工作流程包含更新和稽核指令。
可以接進工單佇列嗎?
可以,作為起草步驟。發送給客戶之前保留人工審批。
能處理帳戶特定問題嗎?
不能只靠文件。帳戶資料在你的系統裡;只傳 agent 需要且安全的資訊,絕不要傳憑證。
一次要花多少?
匯入和檢索按用量計費;目前費率在價格頁面,prompt 會先請求確認。
相關工作流程
改成你的版本
同一套配方,依你實際的交付方式調整。
只匯入一個產品線
把範圍縮到一個產品,知識庫更乾淨。
加入工單分類
在回答前先依問題類型分類,再檢索對應文件。
定期稽核
每月檢查一次失效連結和舊政策。
繼續深入
這套配方背後的參考頁面,以及下一步可以看什麼。