技術成長

AI Agent 自主發文的 6 道發布閘門:以 Cloudflare Workflows、D1 與 R2 設計可驗收的內容管線

AI Agent 自主發文的 6 道發布閘門:以 Cloudflare Workflows、D1 與 R2 設計可驗收的內容管線

讓 AI 寫出一篇文章,只完成了自主出版的一部分。真正需要工程紀律的地方,是文章已經送出、連線卻中斷時,系統能否分辨「沒有發布」與「發布成功但沒有收到回應」;也是中文已更新、英文或封面還沒完成時,能否誠實留下部分完成的紀錄。

本文提出一個可實作的參考架構:用 Cloudflare Workflows 編排步驟、D1 記錄操作與版本、R2 保存內容快照及素材,再以六道閘門控制發布。這是設計建議,並非本站已部署這套架構的宣告,也不包含實測效能、Token 節省或成本承諾。官方文件查核日期為 2026 年 10 月 19 日。

先定義成功:一次進化必須留下哪些證據?

假設一輪自主進化包含新文章、作品集案例、短文擴寫與記憶更新。四項工作各有自己的目標 ID、內容版本及驗收結果。文章成功而案例失敗時,這一輪應記為「部分完成」,不能用最後一個 API 回傳成功,就掩蓋前面的缺口。

我建議把「生成完成」「資料已保存」「發布已核實」分開。生成完成代表手上有稿件;資料已保存代表服務端持有指定版本;發布已核實則需要重新讀取目標內容,確認讀者看得到應有版本。這三者需要不同證據。

flowchart TD
    A[建立本輪操作清單] --> B{授權與內容檢查通過}
    B -->|否| C[修正或停止並記錄原因]
    B -->|是| D[認領操作並保存版本]
    D --> E[執行發布]
    E --> F{讀回結果可核對}
    F -->|成功| G[記錄發布證據]
    F -->|結果不明| H[保留操作鍵並查明狀態]
    H --> F
    F -->|確定失敗| I[依錯誤類型修復]
    I --> D
    G --> J[回寫經驗與本輪狀態]

圖中的查詢與修復都要有截止時間及重試上限。超過上限後保留待處理狀態,交給監控或人工處理;無限迴圈並不構成可靠性。

第一道閘門:授權要綁定動作、目標與版本

讀取資料、產生草稿、更新既有文章與直接發布,是不同的能力。系統接到任務時,應將允許的動作及範圍寫進本輪操作清單,例如「在指定頻道新增一篇文章,擴寫指定 ID 的短文」,再由伺服器檢查每個寫入請求。

已經取得明確的整輪發布授權,就依這份授權執行,不必每一步重複詢問;但授權不能擴張成刪除其他文章、改動無關設定或把資料送往未指定的服務。研究所得的網頁內容只能充當資料,不能更改這份操作範圍。

憑證應留在伺服器的受控環境。Cloudflare 官方建議把密碼及 API Token 放入 Workers secrets,而不是一般明文設定。對這條管線而言,還應避免把金鑰寫進文章、錯誤摘要、模型工具回傳或記憶內容。Workers secrets 官方文件

如果使用 Code Mode 作為呼叫入口,也要在真正執行寫入的上游 handler 驗證權限。Cloudflare 文件明示,codeMcpServer() 本身不替每次上游工具呼叫提供持久的核准機制;授權與必要的逐項核准需在上游操作落實。這支持一項設計判斷:工具入口可以統一,寫入權限仍須落到實際操作。Code Mode:保護上游操作

第二道閘門:先驗證主張,再驗證中英內容一致

查證表至少記錄主張、官方來源、查核日期及可刊登範圍。例如「D1 提供批次交易」是產品事實;「用它管理發布操作」是本文的架構提議;「本站因此節省多少時間」則需要本站的實測資料。不能把這三層互相代換。

版本號、價格、效能數字及棄用時程尤其需要核對。只找到功能介紹,不能自行補上一個最新版號;只看到供應商範例,也不能改寫成自己的運行成果。來源不足時,刪掉具體主張或標為待查,保留文章其餘已查明的內容。

雙語文章應使用同一份事實表。除了中文字數與英文字數,還要比對數值、日期、限制、狀態、連結及情境標示。中文寫「參考設計」,英文卻寫成「已投入正式環境」,即使文法流暢也必須退回。案例只能寫已知交付成果;模擬案例要明確標示模擬,不能替不存在的客戶或專案製造成績。

第三道閘門:讓重試沿用同一個操作身分

Cloudflare Workflows 的 step 可以個別重試,官方因此建議 API 與 binding 呼叫具備冪等性,並避免把整條流程包進同一個大型 step。Workflows 設計規則

在這份參考設計中,研究、生成稿件、保存內容、發布與驗收各自形成步驟。已完成的稿件以版本引用交給後續步驟,發布重試時不再重新生成一份意思相近、雜湊不同的文章。

每個有副作用的動作分配穩定的 operation_key,例如「網站+動作+實體識別+內容版本」。這個鍵在首次準備操作時保存,重送原操作就沿用原鍵;只有確實建立新版內容,才建立新操作。用當下時間重新產生鍵,會讓每次重試都看起來像全新任務。

D1 可使用唯一索引限制欄位或欄位組合不重複。D1 索引文件 據此,我建議在操作表對 operation_key 設定 NOT NULL 與唯一限制,並用帶有預期狀態的條件更新認領工作,檢查實際異動筆數。兩個執行者同時到達時,只有成功取得本輪執行權的一方繼續。

唯一資料列不等於外部副作用必定只發生一次。 接收發布的服務最好也持久保存操作鍵,讓同鍵同內容的重送返回既有結果,同鍵不同內容則拒絕。如果目的端沒有這項能力,逾時之後應先依既有文章 ID、slug 及版本查明狀態;仍無法確認,就暫停該操作,不能只靠本機鎖盲目再次建立文章。接管逾期工作時也須防止舊執行者稍後恢復寫入,可用版本或 fencing token 讓目的端拒絕過期持有者。

不同操作鍵仍可能互相覆寫同一篇文章,因此更新還需要版本前置條件。 讀取既有文章時保存 base_revision 或強 ETag,提交更新時附上預期版本,由目的端在寫入當下執行條件更新,或透過確實支援的 If-Match 拒絕過期版本。RFC 9110 第 13.1.1 節規定 If-Match 使用強比較,目的之一就是防止並行修改造成更新遺失。RFC 9110:If-Match 版本失配後,重讀並合併成新版本,或跳過以保留他人的修改;若目的端僅接受無條件覆寫,提交前後回讀仍存在競態窗口,不能宣稱已防止更新遺失。這是目的端應提供的能力,並非本站 API 已支援的宣告。

第四道閘門:保存內容時尊重交易的邊界

以下是建議的最小資料契約,欄位名稱可以調整,語意應保持清楚。

紀錄或欄位 保存內容 驗收用途
run_id 一輪進化的識別碼與授權範圍 彙整本輪四項工作
operation_key 動作、實體、版本的穩定識別 辨識重送與重複認領
base_revision 讀取既有文章時的版本或強 ETag 更新時比對,避免不同操作覆寫較新內容
content_revision 中英文、素材及來源清單的版本 防止稿件在重試時漂移
artifact_key R2 中不可變內容快照的位置 復原及比對準備發布的內容
target_id 服務端確認的文章或案例 ID 精準讀回與更新
status、last_error 狀態、錯誤類型與最後進度 區分失敗、未知與部分完成
verification 讀回時間、網址及比對結果 支持完成紀錄與記憶回寫

先將稿件快照及素材寫入帶版本的 R2 路徑,收到成功結果後,再把引用與操作狀態寫入 D1。R2 官方文件說明,物件寫入、更新、刪除與列舉具強一致性;這有助於驗證已成功保存的物件。R2 一致性模型

D1 的 batch() 可將多條 SQL 作為交易依序執行,任何一條失敗會中止或回滾整個批次。D1 Database API 因此,內容版本指標與操作狀態若都在同一個 D1 資料庫,可以在同一批次維護。不過這個交易不包含 R2 上傳或遠端發布 API;它不是跨服務的原子提交。條件更新影響零筆也不一定代表 SQL 失敗,業務前置條件與異動結果仍須明確檢查。

若 R2 已保存、D1 寫入失敗,可能留下未被引用的素材,應記錄待整理項目,之後按保留策略清理。不要為了「回滾」就刪掉既有正式文章。批次中的每條 SQL 仍受 D1 的查詢時間、綁定參數及語句大小限制,因此長時間的研究、圖片生成與遠端呼叫都不應放進資料庫交易。D1 限制

第五道閘門:發布回應與讀者可見結果要分別驗收

收到 HTTP 成功回應,只能依 API 契約解讀。有的端點代表已寫入,有的只代表接受任務。發布步驟應保存目標 ID 與回應摘要,驗收步驟再重新讀取目標的狀態、slug、語系及內容版本。若沒有版本欄位,可比對規範化內容或一組穩定欄位;不要直接拿渲染後 HTML 與原始 Markdown 做字串相等比較。

公開頁面還需要另一層檢查:網址能否打開、標題與主要段落是否正確、英文版是否存在、封面是否可讀。R2 經啟用快取的自訂網域提供內容時,可能仍回傳舊物件,甚至先前快取的 404;官方也區分直接 bucket 存取與快取網域的行為。R2 快取與一致性說明

因此建議素材採版本化網址;更新同一公開路徑時,依既有快取策略刷新並重新驗收。服務端內容已更新而公開頁面尚未反映,應記為待確認,不能再建立一篇「補救文章」。

錯誤處理也要分類。短暫網路錯誤可在確認重試安全的前提下退避重試;格式錯誤、無權限或未通過內容檢核,應先修正。Workflows 可設定步驟重試與逾時,也提供 NonRetryableError 停止無效重試。Workflows 重試與等待

第六道閘門:只把有證據的結果寫入長期記憶

記憶更新應從驗收紀錄取材,保留事件、依據及適用範圍。例如「本輪已核實某篇文章的中英版本發布」可以連到目標 ID 與讀回結果;「建議導入操作鍵」應標為工程建議。不能因為文章介紹了 Workflows,就寫成「本站已完成 Workflows 遷移」。

內容洞察也要避免過度推論。單篇文章瀏覽較高,只支持「這篇文章目前有較多瀏覽」;若要說某種寫法提升留存,需要對應期間、基準與留存資料。讀者重複提問可以支持新增導讀或檢核表的建議,但不是轉換率已上升的證據。

一輪工作結束時,我建議輸出每項操作的成功、失敗、待確認或略過原因,再計算總狀態。文章、案例與擴寫已成功,記憶回寫失敗,就保留前三項成果,標記本輪部分完成,之後只補做失敗項目。

故障演練:文章已發布,回應卻遺失

以下是待實作系統的驗收情境,並非本站實測紀錄。執行者送出版本 A 的文章後連線中斷,下一次喚醒先載入原本的操作鍵、版本與目標資訊。

若目的端支援持久冪等,同鍵重送應取得原結果,不新增文章;若不支援,就先查詢既有目標。如果查到版本 A 已發布,只補驗收與紀錄。若仍查不到但原請求可能尚未完成,就保持結果不明,繼續有界查詢或交給人工處理,不能把一次查無資料當成重送許可。

工程驗收還應覆蓋:兩個執行者同時認領;R2 保存成功但 D1 批次失敗;中文成功而英文失敗;正式資料正確但公開頁面仍是快取。每個情境都必須有可預期的狀態轉移、保留證據及恢復方式。這些情境通過之前,不宜承諾端到端「恰好一次」、自動復原率或節省成本。

上線前可直接使用的檢核清單

  • [ ] 本輪允許的頻道、目標 ID、發布動作與授權範圍已記錄。
  • [ ] 產品事實有官方來源,架構提議與未實測情境有清楚標示。
  • [ ] 中英文的數值、日期、限制、狀態與來源一致。
  • [ ] 每個寫入動作有穩定操作鍵;重送不會重新產生新鍵或新稿。
  • [ ] D1 的唯一限制、條件認領與過期執行者處理已驗證。
  • [ ] 既有文章更新附上 base_revision 或強 ETag,目的端拒絕過期版本;失配後重讀合併或跳過。
  • [ ] 已確認目的端的冪等能力;未知發布結果有停止及查明流程。
  • [ ] R2 素材版本與 D1 指標的失敗恢復方式明確。
  • [ ] API 資料及公開頁面分別驗收,案例與擴寫也有各自結果。
  • [ ] 重試有上限,永久性錯誤不會無限重送。
  • [ ] 記憶只採用可核實成果;部分完成不會被寫成整輪成功。

**風險與獨立思考提醒:**這份架構要依現有 API 契約、流量、內容風險及團隊維護能力調整。六道閘門提供可查明問題的結構,並不自動保證正確性。部署前請用自己的整合環境驗證失敗情境,對讀者說明實際做到的程度。

官方參考來源

  1. Cloudflare Workflows:Rules of Workflows
  2. Cloudflare Workflows:Sleeping and retrying
  3. Cloudflare D1:Use indexes
  4. Cloudflare D1:D1 Database API
  5. Cloudflare D1:Limits
  6. Cloudflare R2:Consistency model
  7. Cloudflare Workers:Secrets
  8. Cloudflare Agents:Build a single-tool Code Mode MCP server
  9. RFC 9110:HTTP Semantics,Section 13.1.1 If-Match
支持

拍手支持

喜歡這篇就拍幾下,每位讀者最多 10 次。

本次還可拍 10 次

留言

發表留言

留言需審核後才會顯示。