Felo API PlatformFelo API Platform

客服

用你自己的文件回答客服問題

建立一個 LiveDoc,匯入幫助中心和內部 runbook,檢索能回答工單的段落,再讓模型只根據這些證據回答。

建置時間20 分鐘難度入門更新於2026-10-29
適合誰客服團隊客戶成功Helpdesk 建構者

複製 prompt

把方括號裡的欄位替換掉,然後貼到 Claude Code、Codex 或任何能存取終端機的 AI。它會安裝 Felo skill、在花額度前詢問,並執行這套工作流程。

只用我們的文件回答這個支援問題:[客戶問題]。

知識庫:[幫助中心 URL 或 LiveDoc short_id]。升級路徑:[負責人或佇列]。
可用客戶脈絡:[方案、地區、產品](不要索取密碼或支付資料)。

輸出:
1. 兩到四句直接回答。
2. 支撐回答的文件段落,附資源標題。
3. 客戶的下一步。
4. 內部備註:使用的資源和相關度分數。

規則:
- 只根據檢索到的段落回答。沒有命中或相關度低時升級,絕不猜測。
- 不要編造政策、退款、定價或帳戶操作。
- 不要引入客戶私密資料、憑證或支付資訊。
- 在消耗額度做資料匯入或檢索前先詢問。
- 不要把回答傳送給客戶;回傳給我審閱。

複製的內容也包含安裝步驟和安全規則。

你會得到什麼

一次執行的範例輸出,不是即時生成。

回答範例(節錄)

回答:你的方案在每月 1 日續約。信用卡扣款失敗後會重試三天,然後席位暫停。

來源:「帳單常見問題」 - https://example.com/help/billing

如果這裡沒有涵蓋:帶上發票 ID 升級到帳單佇列。

實際呼叫

給開發者:同一套工作流程的可複製程式碼,依執行順序排列。

展開實際 API 呼叫
  1. 建立知識庫

    用 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"
    }
  2. 匯入公開幫助中心

    把幫助中心 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" }
    ]
  3. 補充非公開文件

    把內部 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
  4. 檢索問題相關證據

    用語意檢索拿到最相關的段落和分數。

    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
      }
    ]
  5. 只基於證據回答

    讓模型只使用檢索到的段落,並在沒有命中時升級。

    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 會先請求確認。

相關工作流程

改成你的版本

同一套配方,依你實際的交付方式調整。

只匯入一個產品線

把範圍縮到一個產品,知識庫更乾淨。

加入工單分類

在回答前先依問題類型分類,再檢索對應文件。

定期稽核

每月檢查一次失效連結和舊政策。

這套配方背後的參考頁面,以及下一步可以看什麼。