AI 產品最容易漏掉的規格,不是 prompt,而是模型呼叫前後的資料與責任。來源版本、工作狀態、失敗原因和人工確認只要有一項沒有定義,「串接 AI」就仍是一個技術動作,不是一項可驗收的產品功能。
上篇把 Content Workflow Platform 的 MVP 收斂成一條可驗收工作流。這篇從那個結論往下走:當工作流裡某一步交給 AI,PM 還要補上四份契約,才能讓它成為系統的一部分。
第一層:決策契約先說清楚 AI 能決定什麼
在 Content Workflow Platform 裡,我沒有先做一個共用的 Generate 按鈕,而是把 AI 拆成兩段工作:
source_to_plan
→ 產生三個候選方向
→ 使用者選擇一個方向
→ draft_deliverable
→ 產生該方向的候選內容
這樣比一次生成全文多了一個步驟,卻保留了最重要的產品決策:模型可以提出選項,但不能替使用者決定哪個方向值得繼續。
第二層:資料契約要讓每個結果回得去來源
如果每次呼叫都把畫面上的文字直接送給模型,事後很難回答:這次用了哪一版來源?套用了哪一版規則?結果是哪一次工作產生的?來源修改後,舊結果還能不能被解釋?
我最後把資料拆成一條可追溯的鏈:
SourceRecord
→ immutable Raw Snapshot / Raw Artifact
→ versioned Context Manifest
→ AI Job + Result receipt
→ Candidate Artifact
→ human-edited Deliverable
→ Manual Publication Record
Raw Artifact 保存原始內容與 hash。Context Manifest 記錄這次允許送給模型的資料版本。Job receipt 保存執行狀態與失敗原因。Candidate Artifact 則保留模型原始候選。使用者真正編輯並保存後,內容才成為 authored Deliverable。
這條資料鏈讓每個結果都能回到來源,也避免模型輸出和人的決定被存成同一筆資料。
模型輸出和人確認的內容不能是同一筆資料
如果模型回傳結果直接進入編輯器,並沿用同一筆資料保存,系統就無法分辨哪些內容來自模型,哪些內容已經被人看過並承擔責任。
這次的設計要求 Candidate 保留原始來源。使用者可以把它帶入編輯區,但經過選擇、修改與保存後,才會形成 authored Deliverable。複製到剪貼簿也不會觸發發布,平台只保留人工發布紀錄。
這個區分帶來三個直接結果:
- 失敗重試不會覆蓋上一個成功候選。
- 頁面重新載入後仍能重建候選來源與目前編輯內容。
- 系統不會把模型成功誤報成內容已被批准或發布。
第三層:執行契約要處理中斷、卡住與重載
第一次瀏覽器端到端驗收揭露的問題,不是模型完全不能回應,而是 AI 工作在真實操作中會經過更多中間狀態。
背景更新曾讓使用者正在看的階段被重設;工作如果沒有先保存成 running,中途關閉後就會留下無法解釋的 queued 狀態;瀏覽器請求沒有 timeout,介面就可能長時間被鎖住;成功結果也必須在重新載入後回到正確平台的編輯器。
修正後,系統採用以下規則:
- 呼叫模型前先保存 running。
- 中斷過久的 queued/running Job 轉成明確失敗。
- 瀏覽器請求有等待上限,不無限鎖住介面。
- 結果保存目標平台,重新載入後回到正確欄位。
- 失敗保留原因與重試入口,不沉默清空上一個成功結果。
這些狀態才是 PM 需要寫進 AI 功能規格的內容。「串接模型 API」沒有涵蓋其中任何一項。
現在能不能執行,和上次有沒有成功,是兩件事
後續 UX 驗收又發現另一個問題:目前服務尚未就緒時,畫面仍可能顯示上一個成功工作的紀錄。兩個訊息都是真的,但放在同一層,使用者會無法判斷究竟是現在不能執行,還是過去沒有成功。
最後介面把它拆開:
- Current readiness 回答現在能不能建立新工作。
- Last Job receipt 回答上一個工作當時發生了什麼。
沒有工作正在執行時,不應顯示「停止 AI 工作」。服務尚未就緒時,操作也要回傳具體原因,不能只留下沒有說明的 disabled 按鈕。
這個原則不只適用於 AI。任何依賴外部服務的功能,都應該把目前可用性和歷史結果分開。
第四層:系統邊界不能被私人模型服務綁住
這個平台最後使用私人模型服務,但產品核心沒有綁定該服務。Source、Plan、Deliverable、Asset、Review 與 Today 屬於通用核心;模型端點、私人連線與憑證留在本機 Connector 邊界。
這個分離處理的是實際風險:
- server-only key 不進入瀏覽器與公開程式碼。
- Connector 未就緒時,核心資料與歷史結果仍可讀取。
- 不用付費 fallback 或自動重試掩蓋連線問題。
- 未來替換模型服務時,不必重寫產品資料模型。
完成版維持 loopback-only,沒有帳號系統、公開服務或自動發布。這些不是忘記做的功能,而是這一版產品刻意保留的 operating boundary。
串起上下篇:先定義工作,再定義 AI 如何參與
上篇處理問題、範圍與驗收,回答「要做什麼」。下篇處理資料、執行、責任與系統邊界,回答「AI 要怎麼參與」。兩篇合起來,才是一條完整的 AI 軟體 PM 路徑。
下一次看到「串接 AI」需求時,我會用以下六題檢查下篇是否成立:
- 模型這次讀到的是哪一版來源與 Context?
- Job 有哪些狀態?中斷、timeout 與重新載入怎麼處理?
- 結果如何連回來源、Job、目標平台與使用者選擇?
- 模型結果是 Candidate,還是已經由人確認的 Deliverable?
- 模型服務不可用時,介面如何解釋,舊資料是否仍可使用?
- 哪些憑證、成本與外部副作用必須被隔離或禁止?
如果上篇沒有先定義工作流,這六題會失去產品脈絡;如果下篇沒有回答這六題,上篇的驗收條件也無法落到真實 AI 行為。兩邊接起來,AI 才從一個會回傳文字的 endpoint,變成能操作、能測試,也能在失敗後復原的產品能力。
上一篇:AI 內容工作流平台專案拆解(上):PM 如何把模糊需求收斂成可驗收 MVP