CodeGym /課程 /ChatGPT Apps /事件管理與營運循環

事件管理與營運循環

ChatGPT Apps
等級 19, 課堂 3
開放

1. 什麼是 ChatGPT Apps 世界中的事件

在傳統 Web 中,事件通常像是「伺服器掛了」、「500 錯誤暴增」、「latency 翻倍」。ITIL 的正式定義:事件是服務的非預期中斷或服務品質的下降。

在 ChatGPT Apps 與 GiftGenius 的世界更複雜:我們多了一層模型,可能會:

  • 在一切可用的情況下,卻沒有呼叫所需的 tool;
  • 以錯誤的參數呼叫 tool;
  • 忽略你的 MCP,直接「幻覺」出結果。

因此,事件不僅是 HTTP 500,還可能是這樣的情況:所有後端監控都一片綠,卻大量使用者抱怨:「機器人很笨、沒顯示禮物」——因為模型不再呼叫 suggest_gifts,或把參數搞混。這是品質事件(Quality incident)。

將事件按類別思考很實用:

類別 症狀範例 指標範例(SLI)
Availability MCP 無回應,ChatGPT 中出現「Error talking to app」 % 成功回應 /mcp
Latency 禮物推薦耗時 10+ 秒 呼叫 suggest_gifts 的 p95 時間
Quality 模型不呼叫所需的 tool,或把幣別搞錯 在明確要求時,沒有 tool 呼叫的請求占比
Commerce 結帳無法完成,款項不流動 checkout_success_rate

所謂事件,是指實際指標超出預先約定的 SLO 範圍的時刻。比如:

  • 我們約定:禮物推薦的 p95 < 4 秒。現在變成 9 秒;
  • 我們希望每週 99% 的 checkout 成功,結果只有 94%;
  • 我們預期在購買情境中,模型幾乎都會呼叫 create_checkout_session,但從日誌看到「漏叫」急遽上升。

重要:事件不是「有人在聊天室抱怨」。抱怨只是觸發器;是否認定為事件,需依據 SLO/SLI 與儀表板。

2. SLO/SLI 如何轉變為事件

在 observability 模組中,你已經設定了關鍵指標:latency、availability、error-rate、checkout 成功率。現在把它們當成「門口的警衛」。

最簡單的情境:我們為 checkout_success_rate 設了 SLO。我們記錄結構化事件日誌:

// MCP 伺服器中的 checkout 日誌事件範例
logger.info({
  event: 'checkout_result',
  request_id,
  user_id,
  checkout_session_id,
  status: 'success', // 或 'failed'
  error_code: null,
});

在這些日誌之上建構指標:最近 N 分鐘/小時內,所有 checkout_result 中 status = "success" 的比例。當比例低於門檻(例如 10 分鐘內低於 95%),監控會將警報發送到 on-call 頻道。這就是事件偵測:SLI 超出 SLO 範圍。

同樣地,警報也可能因以下而觸發:

  • error_rate 在 suggest_gifts、search_products 等工具上升;
  • p95/p99 latency 上升;
  • workflow_completed 數量異常下降(使用者走不到流程終點);
  • 在沒有流量成長的情況下,LLM 成本異常上升(經濟性事件)。

這一切之所以可行,是因為我們使用結構化日誌,而不是寫「checkout 又不對了」。當指標與警報就緒,我們學會了察覺異常。下一個問題:偵測之後會發生什麼?由誰、如何回應?

3. 事件生命週期:從偵測到事後檢討

為了不總是陷入救火狀態,最好描述一個標準管線。許多 SRE 團隊將其形式化為一串步驟:

flowchart TD
    D["Detection (偵測)"] --> T["Triage (嚴重性評估)"]
    T --> M["Mitigation (快速止血)"]
    M --> R["Resolution (最終修復)"]
    R --> P["Post-mortem (檢討與改進)"]

以 GiftGenius 為例拆解各階段。

Detection — 如何知道情況不妙

問題的發現可以是自動或手動。

自動偵測——也就是基於 SLO/SLI 的監控警報:

  • PagerDuty / Opsgenie / 電子郵件 / Slack 機器人發出警報:SEV-1:10 分鐘內 checkout_success_rate < 60%;
  • 延遲警報:p95(suggest_gifts) > 10 秒;
  • 成本異常:「在 workflow_completed 數量相同的情況下,LLM 成本翻倍」。

手動偵測——當客服(或直接在你的 Telegram)收到大量訊息:「無法付款」、「小工具一直在轉圈」。有時正是這些訊息在監控反應之前就凸顯了問題。

實務結論:即便尚未有完美的監控,也請養成一個習慣——遇到大量用戶抱怨時,用指標的視角去看:「背後對應的是哪個指標?要如何量測?」

Triage — 分類與優先順序

偵測後要回答兩個問題:有多糟,以及誰要去修。

可以用一個簡單的嚴重性等級:

  • SEV-1:嚴重——使用者無法購買,App 的關鍵流程無法運作(例如有流量時 checkout=0)。
  • SEV-2:嚴重但為降級狀態——部分使用者無法完成流程,延遲大幅上升,但非完全不可用。
  • SEV-3:次要缺陷——某個附加 tool 偶爾會掛,只影響邊界案例。

對 GiftGenius 而言,commerce 事件幾乎總是 SEV-1:只要錢不動,不只是技術問題,還會直接打擊營收與信任。

同一步也會指派 on-call(或如果你是單人團隊,就是你自己),並做出決定:「是的,這是正式的 SEV‑1 事件,依 runbook N 執行」(runbook 是事先寫好的逐步指引;其結構在後文說明)。

Mitigation — 先止血

Mitigation 不是尋找根因,而是採取快速措施,讓使用者少受影響。例子:

  • 回滾最近的 MCP/Agents/ACP 版本;
  • 關閉有問題的功能旗標;
  • 將 GiftGenius 切到「瀏覽」模式:顯示推薦,但不允許完成購買;
  • 暫時降載(rate limiting)或停用重量級工具。

我們的 MCP 中「降級模式」的典型程式碼:

// 偽代碼:可快速切換的全域旗標
let checkoutDisabled = false;

export function setCheckoutDisabled(value: boolean) {
  checkoutDisabled = value;
}

export async function createCheckoutSession(args: CheckoutArgs) {
  if (checkoutDisabled) {
    // 告知模型目前無法購買
    return {
      error: 'checkout_temporarily_disabled',
      message: '付款暫時無法使用,請向使用者說明。',
    };
  }

  // 建立會話的常規邏輯
}

在功能旗標系統中,你可以把 setCheckoutDisabled(true) 當作 mitigation 的一部分:至少讓使用者看到真實的說明訊息,而不是 500 或卡住的付款。

Resolution — 最終修復

當「出血止住」後,你就有時間找出根因並修復它:

  • MCP/ACP 代碼中的 bug;
  • 外部供應商問題(Stripe、支付閘道);
  • OpenAI API 的限制(429、過載);
  • prompt 損壞或更換了模型,以致不再呼叫 tool。

Resolution 通常包含:

  • 修復(patch/rollback/設定調整);
  • 先部署到 staging,之後再到 production;
  • 檢查所有 SLI/SLO;
  • 將旗標恢復為正常狀態。

Post-mortem — 從錯誤學習

事件之後,特別是 SEV‑1/SEV‑2,要做 post-mortem:一份文件,誠實回答:

  • 發生了什麼(事實與時間線);
  • 如何發現;
  • 如何回應;
  • 哪些做得好、哪些做得不好;
  • 要做哪些變更避免再犯。

Post-mortem 不是找戰犯,而是改進系統與流程。根據它更新 runbook、警報,有時甚至是架構。

4. 角色與責任:即使你是「一人團隊」

要讓上述事件管線在現實中運作,必須預先約定:在失火期間,到底是誰對哪些決策負責。即使你的團隊小到能擠進同一部電梯,也值得在事件期間形式化角色,降低混亂。

常見的分工:

  • On-call 工程師——第一時間接到警報,並對穩定性相關的技術決策負責(回滾、feature flags、暫時性遮罩)。
  • 事件指揮官(Incident commander)——主導流程:記錄時間線、決定任務優先順序、避免團隊瞎忙。在小團隊中,可能就是同一位 on-call 換上不同「帽子」。
  • 對外溝通——負責與使用者與業務利害關係人的溝通:Slack、狀態頁、App 介面(widget/聊天)、ChatGPT 商店。
  • 記錄員(Scribe)——記下重要步驟與事實,後續根據這份筆記撰寫 post-mortem。

在一人團隊中,這四個角色都是你自己;刻意地切換模式會有幫助:「現在我是工程師在修」、「現在我要對外溝通」、「現在我要記錄時間線」。

5. Runbook:用手冊取代記憶

Runbook 是一份文件,逐步說明遇到某種事件時要做什麼:看哪些圖、按哪些按鈕、哪些東西可以犧牲。它能大幅減少即興發揮與壓力。

Runbook 的結構

通常 runbook 包含:

  1. 事件的簡短描述與偵測方式。例:「ACP checkout 錯誤上升 > 5%,持續 5 分鐘」或「對 >20% 請求出現 Error talking to app」。
  2. Scope——受影響的範圍:全量流量、特定地區、特定 tool。
  3. 在哪裡看:儀表板連結(checkout 的 SLO、MCP 的 error-rate、tool_name = create_checkout_session 的日誌)、MCP Inspector 等。
  4. 快速 mitigation 步驟:「檢查 Stripe 狀態」、「回滾 ACP 的最近一次發佈」、「開啟僅推薦不購買的模式」。
  5. 最終分析與修復的步驟。
  6. 事後需要更新的內容:警報、程式碼、文件。

GiftGenius 的迷你 runbook 範例(checkout 掛了)

用結構化資料的方式描述,貼近程式碼:

type Severity = 'SEV-1' | 'SEV-2' | 'SEV-3';

interface RunbookStep {
  title: string;
  description: string;
}

interface Runbook {
  id: string;
  title: string;
  severity: Severity;
  detection: string;
  steps: RunbookStep[];
}

export const checkoutFailureRunbook: Runbook = {
  id: 'rb-checkout-failure',
  title: 'GiftGenius 的 checkout 錯誤率上升',
  severity: 'SEV-1',
  detection: '警報:10 分鐘內 checkout_success_rate < 60%',
  steps: [
    {
      title: '檢查外部服務狀態',
      description: '查看 Stripe 與 ACP backend 的狀態,確認沒有全域性故障。',
    },
    {
      title: '檢查最近的發佈',
      description: '確認過去 30 分鐘內是否有 MCP/ACP 部署;必要時回滾。',
    },
  ],
};

在真正的 runbook 裡,你會加入更多步驟:開啟唯讀旗標、在 widget 顯示橫幅、收集日誌以備 post-mortem。

Commerce 事件時給 widget 的文案範例

在 runbook 中預先設計使用者訊息很有幫助。例如,GiftGenius 的 widget 可以顯示:

«我們目前遇到付款的臨時技術問題。您仍可先保存喜歡的禮物點子,稍後再完成購買。」

之後就能把這段文案綁定到 UI 狀態:

// Widget 狀態的偽代碼
const [checkoutAvailable, setCheckoutAvailable] = useState(true);

if (!checkoutAvailable) {
  return (
    <Alert>
      付款暫時無法使用。您仍可瀏覽並保存禮物點子。
    </Alert>
  );
}

6. 在 GiftGenius 的實作:環繞事件的程式碼

為了不讓主題只停留在流程,來看幾段直接協助事件管理的程式碼。

MCP/Backend 的 health-check 端點

最簡單但重要的工具——health check。在 Next.js 16 可以透過 route handler 實作:

// app/api/health/route.ts
import { NextRequest, NextResponse } from 'next/server';

export function GET(_req: NextRequest) {
  // 可加入資料庫、佇列等檢查
  return NextResponse.json({
    status: 'ok',
    mcp: 'healthy',
    timestamp: new Date().toISOString(),
  });
}

監控系統會定期輪詢 /api/health。若開始出現逾時或 5xx,而非 200 OK,這就是 Availability 事件的明確信號(MCP 不可用)。

依指標分類事件

在分析服務或管理後端腳本中,可保留一段簡單的嚴重性判定邏輯:

type Severity = 'SEV-1' | 'SEV-2' | 'SEV-3';

interface IncidentContext {
  checkoutSuccessRate: number; // 0..1
  giftSearchErrorRate: number; // 0..1
  p95GiftSearchMs: number;
}

export function classifyIncident(ctx: IncidentContext): Severity | null {
  if (ctx.checkoutSuccessRate < 0.6) return 'SEV-1'; // 款項不流動
  if (ctx.giftSearchErrorRate > 0.3 || ctx.p95GiftSearchMs > 8000) return 'SEV-2';
  return null; // 暫未構成事件
}

可以用排程或由監控觸發這段:當回傳 SEV‑1 時,自動在你的系統中建立事件並通知 on-call。

記錄事件的關鍵動作

事件不只是指標,還包括事件本身的生命週期:何時建立、變更、關閉。最好在獨立日誌中記錄。

function logIncidentEvent(event: {
  incidentId: string;
  type: 'created' | 'mitigated' | 'resolved';
  severity: Severity;
  requestId?: string;
  message: string;
}) {
  logger.warn({
    level: 'WARN',
    service: 'incident-manager',
    ...event,
    timestamp: new Date().toISOString(),
  });
}

例如,當 GiftGenius 開啟「唯讀」模式時:

setCheckoutDisabled(true);
logIncidentEvent({
  incidentId: 'inc-2025-11-21-001',
  type: 'mitigated',
  severity: 'SEV-1',
  message: 'Checkout disabled, app switched to recommendations-only mode',
});

之後可輕易將這些事件與時間序列指標對照。

7. 營運行事曆:「耶,修好了」之後的生活

事件管理不僅是救火,也是規律的預防。在 SRE 的實務中,營運循環常以營運行事曆描述,包含定期檢視 SLO、成本與安全。

可以按週期性來分配活動。

每週

每週(或雙週)可:

  • 檢視主要 SLO:latency、error-rate、checkout 成功率、各類事件的占比;
  • 查看本週是否有「自動消退」的警報,決定是否需調整門檻;
  • 簡短檢討至少一個事件(即使是 SEV‑3)——鍛鍊 post-mortem 的肌肉。

每月

每月建議:

  • 檢視成本(LLM、ACP/Stripe 手續費、基礎設施)並對照營收——呼應第 19 模組的第 1–2 題;
  • 檢視產品指標:activation、retention、workflow_completed → checkout_success 的轉換——呼應行銷與成長的模組;
  • 瀏覽 security 日誌找異常:奇怪的登入模式、授權錯誤、異常的請求高峰(銜接安全模組)。

每季

每季你會:

  • 輪換密鑰:OpenAI、Stripe、OAuth client 等 API 金鑰;
  • 檢查 SLO 是否過時:也許 App 成長後 p95 2 秒而非 1 秒是合理,或相反地可以收緊目標;
  • 檢視 runbook:新增事件類型、更新相依(SDK、MCP 規格等)。

行事曆可以只是 Wiki 頁或 GiftGenius 儲存庫裡的 README:重點是要「活著」並持續更新。

8. 事件、金錢與產品:為何 commerce 的火最燙

第 19 模組整體談的是 App 的經濟與「營運生命」,事件在此與金錢緊密相連。Commerce 事件——例如結帳失敗、款項被凍結或重複扣款——幾乎總是比隨機的禮物搜尋逾時更高優先級。

原因很簡單:

  • 此刻的直接營收損失;
  • 信任風險(被扣款卻拿不到商品的使用者很難回來);
  • 潛在的法律與聲譽後果。

因此,在你的 GiftGenius 事件目錄中,commerce 事件應明確標示為 SEV‑1,且要有嚴格的反應 SLO(例如「on-call 需在 15 分鐘內回應,1 小時內完成 mitigation」)。

經濟異常(例如 LLM 成本在流量不增的情況下突然上升)也是事件,但通常屬於 SEV‑2:它不會立刻破壞 UX,但若忽視,可能吃掉所有毛利。

從產品角度看,任何大型事件都是思考的契機:

  • 流程是否過於複雜(也許更簡單就更可靠);
  • 是否需要加入 fallback 情境:例如 MCP 無回應時,模型至少回傳無外部資料的建議;
  • 是否需要調整 UX,以誠實告知問題,而非隱藏它們。

9. 迷你練習(自行完成)

雖然是講座,但強烈建議你在自己的 GiftGenius 上實際完成以下步驟:

  1. 在同一份文件中描述至少兩個 runbook:
    • 「大量付款(checkout)錯誤」;
    • 「MCP 無回應/ChatGPT 顯示 Error talking to app」。
  2. 制定一個月的營運行事曆:
    • 每週要看哪些 SLO;
    • 月底要做哪些成本檢視;
    • 要涵蓋哪些基本的 security 檢查。

這只花幾個小時,但會徹底改變你看待自己應用的方式:它不再只是程式碼,而是活生生的服務。

ChatGPT Apps 事件管理中的常見錯誤

錯誤 №1:「事件只有在全部掛掉時才算」
許多人習慣只把 MCP 或資料庫完全掛掉算作事件。在 AI‑Apps 中,往往更痛的是「柔性」的品質事件:模型不再呼叫所需的 tool、checkout 流程變得混亂、使用者到不了終點,雖然 HTTP 指標一片綠。如果你不把這些情況視為事件並加以檢討,App 的品質會在不知不覺中退化。

錯誤 №2:缺乏明確的 SLO 與「正常運作」邊界
沒有正式的 SLO,關於事件的爭論就會變成「我覺得很慢」對上「我本機很快」。這就是為什麼 SLO 被視為事件管理的基礎:它讓嚴重性變得客觀。

錯誤 №3:用即興代替 runbook
常見畫面:警報一來大家就慌了衝上線上環境,有人回滾版本,有人改設定;一小時後「好像修好了」,卻沒人記得究竟是什麼奏效。沒有 runbook,每個事件都是小型混亂,團隊也無從學習。就算只有一份簡單的 checkout 事件 runbook,也能大幅降低壓力。

錯誤 №4:忽視與使用者的溝通
有時工程師默默修系統,使用者此時只看到「轉圈圈」與「發生未知錯誤」。對 commerce 情境尤其有害:人們會為金錢著急。請事先備好 widget、App 說明,以及必要時對外管道的訊息模板,誠實說明問題與預計修復時間。

錯誤 №5:沒頭沒腦地怪「OpenAI 的錯」,卻不檢討自己那一段
把一切歸咎為「OpenAI 在當機」很容易,但實務上,即使上游出狀況,你仍可在自己的區塊做很多事:正確處理逾時與錯誤、切換到無 MCP 的模式、降低重試次數避免雪上加霜。Shared responsibility 的概念意味著,即便某個供應商不穩,你仍需對你負責的那段負責。

錯誤 №6:沒有 post-mortem 與營運循環
如果事件以「嗯,差不多好了,繼續」結束,而文件、警報、程式碼都不改——系統註定重蹈覆轍。Post-mortem、定期的 SLO/成本/安全檢視,這不是官僚主義,而是與未來的自己與團隊訂定合約,讓一年後的 GiftGenius 更可靠,而不是更脆弱。

1
任務
ChatGPT Apps, 等級 19, 課堂 3
上鎖
Health-check + 迷你可用性面板
Health-check + 迷你可用性面板
1
任務
ChatGPT Apps, 等級 19, 課堂 3
上鎖
透過 feature-flag 實作「read-only checkout」的緩解措施 + 給使用者的誠實訊息
透過 feature-flag 實作「read-only checkout」的緩解措施 + 給使用者的誠實訊息
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION