Loop Engineering - 從提示詞到循環運作

@0x_kaize
英語2 週前 · 2026年7月04日
318K
190
24
15
457

TL;DR

本指南介紹了 Loop Engineering,這是一個用於構建循環運作的自主式 AI Agent 的框架。內容涵蓋五個核心課程:發現、交接、驗證、持久化與排程,以確保自動化流程的可靠性。

我決定把這篇文章獻給如何打造一個可程式化的 Agent,讓它為你完成工作,這樣你就不必每天早上打開電腦,反覆對它下達指令。

它會自己醒來,自己尋找任務,自己發現問題,並將結果儲存並呈現在你的桌上,供你審閱。

前言

Loop 的想法並非憑空出現——在 2026 年 6 月的同一週內,三位業界專家幾乎同時表達了同樣的想法:是時候開始開發這個層級了。

一週後,吳恩達(Andrew Ng)將這個對話置於「從 0 到 1 打造產品」的更廣泛脈絡中,提供了更全面的圖景。

這篇文章從那個故事開始,然後引導你從頭開始建立一個最小但完整的 Loop:5 個動作、6 個部分、一扇說「不」的門,以及一扇人類的門——全部在你自己的機器上運行,並且可以在任何軟體專案中重複使用。

kaize - inline image

來源:華數橙書,Loop 工程:別再問我它是什麼(v260615,2026 年 6 月)

那一週,3 個人點燃了引信

2026 年 6 月: 三個人,彼此之間沒有任何協調,卻在幾天內說了幾乎相同的話。

Peter Steinberger,OpenClaw 的創作者,在 X 上發了兩句話,獲得了 890 萬次觀看:

https://x.com/steipete/status/2063697162748260627

那篇貼文才是這場討論真正的起點。它不是一篇宣言或長文,只是兩行字,為人們已經在默默做的事情命名。

Boris Cherny:我已經不再對 Claude 下提示了,我有正在運行的 Loop。是它們在對 Claude 下提示並決定要做什麼。

Addy Osmani:Loop 工程就是用來取代你作為對 Agent 下提示的那個人。你設計的是執行這個動作的系統。

實務操作比這個名稱早了好幾個月,每個人都在寫 Loop,只是還沒有人給它一個名字。

所以,Loop 現在是我們讓 AI Agent 能夠長期迭代工作以創建軟體的關鍵部分。

kaize - inline image

吳恩達(Andrew Ng) 根據時間尺度,從最內層到最外層排列了三個 Loop:最內層的 Loop 最快,最外層的 Loop 最慢。此外,最外層 Loop 的輸入來自最內層 Loop 的輸出:

Loop

誰在運行它

週期長度

它輸出到外層的內容

Agent 編碼 Loop

Agent 本身

秒 - 分鐘

一個可運行的版本

開發者回饋 Loop

人類 + Agent

數十分鐘 - 數小時

更清晰的產品願景和規格

外部回饋 Loop

使用者 + 團隊

數小時 - 數週

驅動願景演進的真實數據

吳恩達按時間給了我們地圖:三個以不同速度運行的 Loop。Addy Osmani 則按抽象層級繪製了第二張地圖:提示 -> 上下文 -> 工具框架 -> Loop。

kaize - inline image

Loop 工程位於頂層,並增加了工具框架所沒有的三個動詞。它按計時器運行產生輔助程式,並且自我餵養——今天的輸出成為明天的輸入。最後這一點使它成為一個 Loop,而不是將同一個任務執行 N 次。

最重要的直覺: 同一個錯誤在每個層級的成本都不同:

層級

它關心什麼

核心問題

提示工程

撰寫提示

要對模型說什麼

上下文工程

視窗中載入了什麼

要提取、總結、清除什麼

工具框架工程

裝備一次運行

哪些工具、哪些動作、怎樣才算完成

Loop 工程

在工具框架之上進行排程

如何讓它自己運行,一輪接一輪

Loop 的設計本質上就是一台讓「輪次數量」變大的機器。從這裡開始的每一個決定——評估器、人類關卡、Token 上限、狀態檔案——都是為了縮短從「錯誤發生」到「有人看到它」之間的距離。

一輪內部發生了什麼:

「Loop」常被誤解為「原地打轉」。它不是,每一輪都有 5 個具體的動作。刪掉任何一個,Loop 要嘛無法運行——要嘛運行了卻毫無進展。

kaize - inline image
  1. 驗證是那個說 「不」 的動作。
  2. 排程是將這一輪餵養到下一輪的動作。

這正是讓它成為一個 Loop 的部分。

對應到我們即將建立的專案: 一個針對小團隊的晨間分類 Loop:

動作

它的作用

在分類 LOOP 中

發現

弄清楚這一輪該做什麼

一個技能讀取 CI / 議題 / 最近的提交

交接

分派任務,並將其隔離

每個發現都獲得自己的工作目錄

驗證

換另一個 Agent 來說不

第二個子 Agent 作為審查者,檢查測試和技能

持久化

將狀態寫入對話之外

PR + Linear 工單 + ./state/triage.md

排程

讓它一輪接一輪地運行

GitHub Actions 的 cron 在 06:00 觸發

下面 5 堂課,每一堂都專注於一個動作。

五堂課 = 一個完整的 Loop。

我們從第一個開始:發現,因為如果 Loop 無法決定今天什麼值得做,之後的一切都無關緊要。

第 1 課 發現:撰寫一個晨間分類 SKILL.md

技能,而不是一堵提示牆。

想像一下,週一早上 6 點,你的筆記型電腦是闔上的,GitHub Action 醒來並啟動 claude --skill morning-triage:它讀取什麼、它判斷什麼是可操作的、它把結果寫在哪裡——所有這些都存在於你即將撰寫的 SKILL.md 中。

Osmani 的關鍵一句話: 自動化應該觸發一個技能——寫下來的、可更新的專案知識,而不是貼到 cron 任務裡的一堵提示牆。貼上去的提示只會在那裡腐爛,因為沒有人會回去更新埋在排程裡面的東西。

你這堂課的任務: 在 .claude/skills/morning-triage/SKILL.md 撰寫一個技能,讓它自己讀取三個來源(CI / 議題 / 提交),自己決定什麼值得做,將結果寫入 ./state/triage.md——並且有一個明確的「停止」部分,說明 Loop 不允許做什麼。

這是起手式——改三樣東西就是你的了:

json
1# .claude/skills/morning-triage/SKILL.md
2---
3name: morning-triage
4trigger: invoked by daily automation
5---
6
7## 讀取(發現的輸入——換成你的儲存庫實際擁有的來源)
8- 自上次運行以來失敗的 CI 運行 # gh run list --status failure
9- 過去 24 小時內開啟的議題 # gh issue list --search "created:>=…"
10- 自昨天以來合併的提交 # git log --since=yesterday
11- 上一次的 ./state/triage.md # 「昨天 → 今天」的交接
12
13## 判斷(天花板——讓 Loop 自己選,不要給它清單)
14對於每個候選項目,決定:
15- 它現在是可操作的,還是雜訊?
16- 它是否阻礙了發布?→ 優先級 = P0
17- 它是否已經被追蹤?→ 跳過
18只保留今天值得建立工作目錄的項目。
19
20## 寫入(持久化——落地到 Markdown,而不是對話)
21附加到 ./state/triage.md:
22| 發現 | 來源 | 優先級 | 狀態 |
23提交檔案,以便明天可以讀取。
24
25## 交接(為第 2 課做準備)
26對於每個保留的發現,輸出一行任務:
27 worktree=fix/<slug>
28 goal=<停止條件>
29
30## 停止(唯一非模板的部分——這裡要仔細思考)
31絕不合併。絕不刪除。
32任何你不太確定的東西 → 放到 ./inbox/ 給人類處理。
33不是 PR。

這裡有三個部分真正發揮作用:

讀取: 這是發現的輸入——列出具體的來源,精確到實際的指令。記住,「讀取上下文」不是一個來源,但 gh run list --status failure 是一個來源。

判斷: 這是整個 Loop 的天花板。Loop 自己決定「可操作 vs 雜訊」——它不會從你那裡收到清單,因為如果你每天早上還在給它清單,那你只是自動化了「執行」,而不是「選擇」。而選擇通常才是成本更高的步驟。無論你的來源有多好,如果這個部分選了垃圾,其他四個動作就是在無價值的工作上空轉。

停止: 這個檔案中唯一不是模板的部分。Loop 會做技能說的一切,而且只會做技能說的事。如果你不寫「絕不合併」——總有一天它會為你合併。

明確畫出紅線:絕不合併,絕不刪除,絕不推送到主分支,任何不確定的東西都放到 ./inbox/ 給人類處理,而不是放進 PR。

還有一件事值得知道: 同樣的技能結構也適用於晨間分類之外:將「讀取」部分換成「昨天的存取日誌 + 新議題 + 當前部署版本」,它就變成了一個夜間網站健康檢查 Loop。在「判斷」部分加一行——「這是否相較於昨天出現了回歸?」——它就增加了跨日比較的能力。

這堂課要預防的疾病——盲目 Loop:

最常見的「看起來像 Loop,但其實不是」的情況:Loop 在運行,但你每天早上仍然在指派工作(「嘿,看看這三個錯誤」)。那是執行的自動化,而不是發現的自動化。

症狀: Loop 從不讓你感到驚訝,因為它只會做你已經知道需要做的事情。

修復: 把「判斷」放進技能裡,讓它自己選擇今天的工作。

在繼續之前,回答這三個問題:

1/ 你的「停止」部分有幾行?

如果只是「絕不合併」——再加一行:這個 Loop 還不應該為你做什麼?(絕不關閉議題 / 絕不推送到主分支 / 絕不同時處理超過 3 個發現……)

2/ 將「讀取」的第一行改寫成一個在你的專案中實際運行的指令

3/ 如果這個技能一年不變——會發生什麼事?

**現在比較一下:貼在 cron 任務裡的一堵提示牆放一年會發生什麼事?

第 2 課 交接:分配工作,並將其隔離

第 1 課的技能剛剛執行完畢。./state/triage.md 現在包含了 5 個可操作的發現。最自然的下一步想法——同時啟動 5 個 Agent,加快速度。而這正是你養出一個糾結 Loop 的步驟:好幾個 Agent 在同一個目錄下編輯同一個檔案,合併日變成了考古日。

解藥只有一行: 每個發現都獲得自己的工作目錄。

git worktree 是 git 內建的機制:一個儲存庫,多個獨立的工作目錄,每個都簽出到自己的分支。git worktree add ../fix-auth fix/auth../fix-auth 開啟一個完全隔離的工作空間。建置、編輯、測試——都不會影響到其他人。一個發現一個工作目錄 = Agent 之間物理隔離。

你這堂課的任務: 撰寫一個腳本,讀取 ./state/triage.md 中的每個發現,為每個發現開啟一個隔離的工作目錄(命名為 fix/<slug>),發送一個 Agent 在裡面起草修復方案——並設定一個並行上限,以免它無限產生。

json
1# 讀取 state/triage.md,每個發現一個工作目錄
2# 修改:MAX_PARALLEL 為你的機器 / 帳單可以處理的數量
3MAX_PARALLEL=3
4
5# 修改:解析方式以符合你實際的 triage.md 欄位
6findings=$(awk -F'|' 'NR>2 && $5 ~ /open/ {print $2}' \
7 state/triage.md | head -n $MAX_PARALLEL)
8
9for finding in $findings; do
10 slug=$(echo "$finding" | tr ' ' '-' | tr -cd '[:alnum:]-')
11
12 # 關鍵行:每個 Agent 的物理隔離
13 git worktree add ../wt-$slug -b fix/$slug
14
15 # 修改:goal 是停止條件,第 3 課的評估器會讀取它
16 claude --worktree ../wt-$slug \
17 --goal "tests in tests/$slug pass and lint is clean" \
18 "draft a fix for: $finding" &
19done
20
21wait # 等待所有並行 Agent 完成
22
23# 關閉規則:Agent 絕不自動合併——工作目錄等待
24# 第 5 課的人類關卡
25echo "所有工作目錄已準備好審查:"
26git worktree list

這裡重要的規則: 絕不在主分支上工作。

主分支是人類審查的著陸跑道——不是 Agent 的工作桌。所有 Agent 都活在 fix/* 的工作目錄上。

限制並行度: 無限制地產生是通往 Token 爆炸的大門(第 5 課會回到這個問題)。根據一個誠實的問題來選擇 MAX_PARALLEL:不是「我的機器能跑多少」,而是「我實際上能審查多少個 PR」。

合併是人類的決定: Stripe 每週透過這樣的 Loop 處理超過 1,000 個 PR,而且人類仍然審查每一個。人類並沒有離開這個流程——他們換了工作桌:從撰寫程式碼變成了審查程式碼。

還有一個值得借鏡的 Stripe 案例細節:他們反直覺地使用了較小的模型,搭配嚴格的確定性關卡,而不是使用可用的最大模型。

這堂課的教訓: 一個嚴格的驗證關卡,在 Loop 工作中勝過原始模型能力。

這堂課要預防的疾病——糾結 Loop:

單一 Agent 的 Loop 看起來完全健康。問題只會在你開始並行的那一天出現——五個 Agent 運行,五個差異在同一個檔案中碰撞,合併就是一場混亂。

修復: 每個任務都獲得自己的工作目錄,絕不讓 Agent 之間共享工作目錄。

在繼續之前,回答這三個問題:

1/ 你把 MAX_PARALLEL 設成了多少——為什麼?

**(錢?機器?還是「我誠實地能審查多少個 PR」?)

2/ 如果一個工作目錄崩潰了——Agent 退出而沒有觸及任何東西

**明天的狀態檔案應該記錄關於它的什麼?

3/ Stripe 使用了較小的模型 + 嚴格的確定性關卡

**而不是最大的模型,這個選擇對你的 Loop 意味著什麼?

第 3 課 驗證:安裝一扇說「不」的門(最重的一課)

這是 Loop 工程中最難的動作,它值得比其他任何一課投入更多心力。

Anthropic 的工程師 Prithvi Rajasekaran,在處理長期運行的 Agent 應用程式時,注意到一件事:要求一個 Agent 給它剛寫的程式碼評分,它幾乎總是會稱讚自己——即使人類一眼就能看出它很平庸。

這不是模型笨:給自己的作業打分在結構上就是有問題的。 當程式碼完成時,Agent 的上下文已經塞滿了它為什麼這樣寫的自我辯護鏈。看著自己的輸出,它看到的不是結果——它看到的是為結果辯護的論證。

把這個放進 Loop 裡,它會放大成一場災難: 每一輪的「這個夠好了嗎?」都是由剛剛寫下它的 Agent 來回答。每一輪都在對自己點頭。運行得越久,它離真正的品質就越遠。這就是點頭 Loop——而且它是這份清單上最昂貴的疾病。

Rajasekaran 的解決方案,用他自己的話說:

「調整一個獨立的評估器使其保持懷疑,遠比讓一個生成器對自己的工作保持批判要容易處理得多。」

這是一個結構性問題,而不是措辭問題。你無法要求一個作者跳出自己的腦袋,但你可以引入一個不同的 Agent,帶著完全不同的指令,從零開始審視程式碼——沒有附加任何自我辯護鏈。

這個類比來自 GAN:一個網路建構,另一個攻擊:製造者和檢查者。同樣古老的銀行規則:匯款的人和批准匯款的人必須是不同的人。

你這堂課的任務——撰寫兩樣東西:

1) 一個評估器系統提示,位於 .claude/agents/reviewer.md,包含五個部分:角色 + 假設 + 檢查 + 使用 + 裁決。

2) 一個 /goal 指令,宣告這個 Loop 的停止條件——由一個獨立的新模型來判斷,而不是由生成器判斷。

json
1# .claude/agents/reviewer.md(修改 3 樣東西)
2角色:對抗性程式碼審查者。
3假設:這段程式碼在證明其無誤之前是 BROKEN 的。
4不要讚美。找出失敗的地方。
5
6# 修改:按你的專案真實的失敗模式來排序「檢查」,
7# 可運行的檢查優先
8檢查,按順序:
9 1. 它能運行嗎?(執行,不要讀取)
10 2. 測試:執行它們,貼上真實輸出。
11 3. 作者跳過的邊界情況。
12 4. 行為是否符合工單?
13
14# 修改:使用哪個 MCP 取決於你在測試什麼——
15# 前端 → Playwright,API → curl/httpie
16使用 Playwright MCP:開啟頁面,點擊,
17截圖,檢查 DOM。
18判斷行為,而不是意圖。
19
20裁決:僅當每個檢查都成立時才 PASS。
21 否則 REJECT + 列出每個原因。
json
1# 停止條件——由一個新的小模型判斷,而不是生成器
2# 修改:換成你的發現的真實可驗證條件
3/goal all tests in test/auth pass and the lint step is clean
4
5# 注意:/goal 和 /loop 不是同一回事
6# /loop = 按間隔重新運行(沒有停止判斷——危險)
7# /goal = 運行直到一個新模型判斷條件為真

兩個 Agent,最好是兩個模型: 「同一個模型,不同的提示」通常會保留相同的盲點。如果可以,也換掉模型。

預設懷疑: 評估器的基線是「假設有問題」——信任必須通過檢查來贏得,而不是預設授予。

判斷行為,而不是意圖: 「這個 JSX 看起來不錯」和「我點擊了按鈕,頁面導航了,這是截圖」是兩個不同的世界。評估器必須行動——執行測試,點擊頁面,而不是讀取程式碼並憑感覺判斷。

附帶理由地拒絕: 一個沒有列出理由的 REJECT 不是拒絕——生成器不知道該修復什麼。

還有終極測試: 你的評估器在過去 5 輪以上是否真的拒絕過什麼?一個在數百輪中從未說過一次「不」的 Loop,在任何真實工作負載上統計上都是不可能的。所以這證明了評估器沒有在運作。

這堂課要預防的疾病——點頭 Loop:

Loop 運行,Agent 撰寫程式碼,同一個 Agent 說「看起來不錯。」每一輪都自我批准,以機器速度堆疊看似合理的錯誤。修復:這整堂課:結構性分離 + 預設懷疑 + 透過行動判斷 + 第三方停止條件。

在繼續之前,回答這三個問題:

1/ 你的評估器是同一個模型配上不同的提示,還是一個不同的模型?為什麼?

2/ 將「判斷行為,而不是意圖」轉化為你的專案中

具體的一句話:「我的評估器不讀取程式碼,它執行

_____,並且只有在看到 _____ 時才 PASS」

3/ 一個「差不多夠好」的新模型有多大可能錯誤地 PASS 你的 /goal 條件?

如果你最可怕的失敗模式是 X——立即在你的停止條件中為 X 添加一個檢查

第 4 課 持久化:讓今天的工作存活到明天

第 3 課結束了。你的評估器判斷了三個發現——兩個 PASS,一個 REJECT。問題:這三個裁決現在存在哪裡?

如果答案是「在上下文視窗裡」——那麼明天早上 6 點,Loop 醒來時會發現上下文已被清空,什麼都不記得了。它會從頭開始重新分類,被昨天未修復的 REJECT 絆倒,可能又派另一個 Agent 去修復它,可能完全錯過它,可能掉進同一個坑裡。

這就是失憶 Loop——每一天都從同一個起點開始。

解藥只有一行: 記憶是寫入磁碟的狀態,而不是上下文。一個 Markdown 檔案、一個 Linear 看板、一個資料庫——一旦被寫下來,Agent 忘記得多徹底都無關緊要。

這兩者經常被混淆,所以釐清差異:

上下文 = Agent 在這一輪看到的視窗 -> 每次重新整理時清除。

記憶 = 跨輪次和天數存活的狀態 -> 寫入磁碟(Markdown / 資料庫 / 看板)。

一個 Loop 僅透過記憶來橋接今天 -> 明天。

你這堂課的任務:

  1. 建立 ./state/triage.md,至少包含 4 個欄位(發現 / 來源 / 優先級 / 狀態)——第 1 課的技能寫入它,第 2 課的工作目錄讀取它。
  2. 連接一個連接器(MCP):PASS 裁決自動開啟一個 PR,REJECT 裁決自動更新工單。
  3. 驗證明天的 Loop 確實可以讀回今天的狀態。
json
1# ./state/triage.md(Loop 的記憶——根據需要修改)
2
3| 發現 | 來源 | 優先級 | 狀態 |
4|-----------------|--------------|----------|------------|
5| auth test flaky | CI #4821 | P0 | 修復中 |
6| null deref | issue 92 | P1 | PR 已開啟 |
7| stale dep | commit a3f9c | P2 | 待處理 |
8
9# 根據需要擴展欄位:last_seen, retry_count, assigned_to
10# 這個檔案必須提交到儲存庫——
11# 否則明天的雲端運行器無法看到它
json
1// .mcp/connectors.json — 將 Loop 連接到外部世界
2{
3 "github_pr": {
4 "type": "mcp",
5 "on_event": "evaluator.verdict.PASS",
6 "action": "open_pr",
7 "branch": "fix/${slug}",
8 "auto_merge": false // ← 必須為 false。人類關卡 = 第 5 課
9 },
10 "linear": {
11 "type": "mcp",
12 "on_event": "evaluator.verdict.REJECT",
13 "action": "update_ticket",
14 "fields": { "status": "Blocked", "reason": "${verdict.reasons}" }
15 }
16}

為什麼每個欄位都很重要: 沒有來源 -> 你無法審計發現來自哪裡。沒有優先級 -> 你無法安排工作順序。沒有狀態 -> 明天無法接續工作。

而這堂課的驗證是你唯一無法偽造的:等到明天。 醒來,檢查——待處理項目還在嗎?未完成的發現是否仍保留其狀態?早上 6 點的運行是否從昨天停止的地方繼續,而不是重新開始?這一個你需要透過運行來發現,而不是透過推理。

伴隨持久化而來的一個安靜紀律——每天讀取一個樣本。

一旦持久化生效,一個陷阱就打開了:Loop 快速產出 PR,你感覺很有生產力——而你對程式碼庫的心理模型卻在不知不覺中過時了。規則:不要讀取所有東西(那會違背 Loop 的目的),但每天讀取一個樣本 PR,並強迫自己解釋 Loop 改變了什麼以及為什麼。

當你無法解釋它的那一刻——你的心理模型已經落後了。在一個平靜的早晨修復它需要十分鐘。在生產事故期間修復它,成本要高得多。

這堂課要預防的疾病——失憶 Loop:

Loop 找到了好的工作,完成了它,然後忘記了自己做過——因為結果只存在於一個被清空的上下文裡。下一輪它會重新發現同樣的工作,或者更糟——重做一遍並覆蓋掉第一次的嘗試。

症狀: 沒有累積的進展,每一天都從同一個地方開始。修復: 磁碟上的狀態檔案。

在繼續之前,回答這三個問題:

1/ 將「記憶 ≠ 上下文」轉化為一句具體的話

來自你自己的專案:「我的 _____ 是記憶,我的 _____ 是上下文」

2/ 明天的 Loop 醒來——它會先讀取 state.md 的哪個欄位

來決定它的第一步?你把那個欄位命名對了嗎,還是你只是為它埋下了一個地雷?

3/ 紀律:你會在一天中的什麼時間讀取你的那一個

**樣本 PR?現在就設定日曆提醒——這是與你自己的約定。

第 5 課 排程:讓它成真,讓它安全,保留一扇門

第 1 到 4 課已經安裝好了,但 Loop 仍然會在你停止按下按鈕的那一刻停止。最後一個動作是一個動詞:把它掛在一個觸發器上。

但這堂課最危險的部分不是把 cron 設錯。而是把 cron 設——因為那時 Loop 才真正獨自運行,一個錯誤就可能讓它整晚空轉,輔助程式產生輔助程式,直到你醒來看到一張你認不出來的帳單。

所以這堂課實際上做了三件事:掛上觸發器,設定上限,保留一扇人類的門。

首先——選擇你的排程器:

json
1雲端(GH Actions) 桌面排程 /loop(在 CC 中)
2運行位置 雲端 你的機器 你的機器
3需要機器開機? 不需要 需要 需要
4需要會話開啟? 不需要 不需要 需要
5最小間隔 1 小時 1 分鐘 1 分鐘
6能看到本地檔案? 否 是 是

決定性的問題:這項工作能離開你的筆記型電腦嗎?

json
1「每分鐘檢查我的本地開發伺服器」
2 → 必須是本地 + /loop(雲端 1 小時的間隔無法觸及它)
3
4「在凌晨 3 點掃描 GitHub 議題並開啟 PR」
5 → 必須是雲端(你的筆記型電腦是關機的——Loop 不能
6 等待它)

還有整個實踐中最狡猾的自我欺騙:把本地計時器當作「在你睡覺時運行」。它不是。它是「在我還在的時候多跑幾輪。」

翻譯後的文字(僅繁體中文,無解釋):

你在此課程中的任務:

  1. 建立 .github/workflows/triage.yml,並設定一個 cron 觸發器來執行 morning-triage 技能。
  2. 設定三個上限:每次執行的預算、每日預算、以及最大重試次數。
  3. 在工作流程的結尾加入規則:PR 永不自動合併,任何不確定的內容都歸入 ./inbox/
json
1# .github/workflows/triage.yml (修改 3 個地方)
2name: morning-triage
3
4on:
5 schedule:
6 - cron: '0 6 * * *' # 修改:你所在時區的 UTC 06:00
7
8jobs:
9 triage:
10 runs-on: ubuntu-latest
11 timeout-minutes: 45 # ← 每次執行上限 · 修改
12 permissions:
13 contents: write
14 pull-requests: write
15 steps:
16 - uses: actions/checkout@v4
17
18 - name: morning triage
19 env:
20 ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
21 DAILY_BUDGET_USD: '20' # ← 每日上限 · 修改
22 MAX_RETRIES: '3' # ← 重試次數上限 · 修改
23 run: |
24 claude --skill morning-triage \
25 --max-retries "$MAX_RETRIES" \
26 --daily-budget-usd "$DAILY_BUDGET_USD"
27
28 - name: 開啟 PR(永不自動合併)
29 run: |
30 # PR 會自動開啟。合併權限保留給人類。
31 gh pr create --draft --base main \
32 --title "[loop] $(date +%F) triage" \
33 --body-file ./state/triage.md
34 # 這裡刻意沒有 `gh pr merge` 指令
35
36 - name: 將不確定的內容歸入 inbox
37 run: |
38 ls ./inbox/ && echo "有待人工審查的項目"

讓你的迴圈在六個月後依然活躍的三條規則:

先設上限,再上線: 三個層級——每次執行超時、每日預算、最大重試次數——必須在第一次自主運行之前設定好,而不是在看到第一張嚇人的帳單之後。Token 上限不是為了省錢。它是一個斷路器,能把開放的風險轉變為可控的風險。一個沒有上限的迴圈,等於把它的花費權限外包給了自己的 bug。

舉例來說:Uber 在四個月內燒光了 AI 預算後,將每位工程師每個工具每月的花費上限設為 1,500 美元。你的每次迴圈上限,就是這個教訓的細化版本。

保留一扇門: PR 永不自動合併。不確定的項目會歸入 inbox。你每天會抽樣閱讀一個。這扇門的存在,不是因為人類一定會走進去,而是因為這扇門存在,讓你保有可以走進去的可能性。 把每扇門都焊死,等到你真的需要進去的那一天,你就會發現鑰匙已經不見了。

確認它真的會醒來。 至少讓它運行 3 次(試運行也算)。最常見的失敗模式是:展示日當天表現亮眼,星期四就掛掉了。「最後一次運行就是展示那天」是「手動迴圈」的診斷標誌。

在 Claude Code 之外也適用—— 這些功能並非綁定特定廠商,只是名稱不同:

json
1功能 Claude Code Codex
2排程 /loop · worker Automations 分頁
3條件式運行 /goal 自動化重新執行 + 評判
4並行隔離 --worktree 背景 worktree
5子 Agent .claude/agents/ .codex/agents/
6外部連接 MCP + 插件 MCP 連接器
7明確技能 SKILL.md $skill-name
8離線運行 Cloud Routines 雲端(規劃中)

問題從來不是「選哪個廠商」。而是「這六項功能是否都已安裝」。

這堂課要預防的疾病——手動迴圈:

四個步驟都做得很好,但沒有設定 cron。這不是一個迴圈——這只是一個你跑過一次就忘記的腳本。

解決方法: 掛上任何一個不依賴你記憶的觸發器。

在上線之前,回答這三個問題:

1/ 你的三個上限的具體數字是多少?

如果一個 bug 整晚都在運轉——哪個上限會第一個擋下來?如果沒有任何一個會擋下來……這說明了什麼?

2/ 你的人類之門長什麼樣子?

(PR 審查 / inbox / 每日抽樣 / 每週對帳?)把它寫下來 = 與自己簽訂合約

3/ 總結性問題: 六個月後,這個迴圈會讓你變得更強(理解力、判斷力、對系統的感知)——還是讓你變成了一台你無法讀懂的機器的看護者?你打算如何避免後者?

四種債務與保持工程師身份

你的迴圈已經建立:它會醒來、尋找工作、自我批評、記住經驗、並安排自己的明天。

當一個迴圈運行時,有四種東西會悄悄累積——它們的共同特點是沒有一種會觸發警報。

json
1驗證債務 未經審核的輸出不斷堆積
2理解力衰退 程式碼庫在增長,你的心智地圖卻沒有
3認知投降 「我不想再仔細審查了」
4Token 爆量 一個 bug 整晚運轉 → 你看到的是帳單

它們會互相餵養: 未經審核的輸出侵蝕你的理解力 -> 被侵蝕的理解力引導你走向投降 -> 投降讓迴圈運行更久、花費更多 -> 進而產生更多未經審核的輸出。

在它第一次獨立運行之前,用這四點審查你的新迴圈:

  • 我的評估器真的會拒絕輸出——它不是裝飾品。
  • 我每天會閱讀一個 PR 樣本,並且能解釋發生了什麼變化。
  • 我保留了說「這是錯的」的習慣。
  • 我的上限是在第一次運行之前設定的,而不是在看到第一張帳單之後。

而這裡是決定一切的關鍵:

同一個迴圈,由兩個人建立,最終可能走向完全相反的方向。一個人用它來加速前進,同時仍然閱讀程式碼並掌握方向——這個迴圈放大了他們已有的判斷力。

另一個人則用完全相同的迴圈,目的就是為了再也不去理解任何東西——六個月後,第一個人變得更敏銳,而第二個人則成了一台他們無法讀懂的機器的看護者。

Addy Osmani:「建立迴圈,但要像一個打算繼續擔任工程師的人那樣去建立它——而不僅僅是按下啟動按鈕的人。」

迴圈讓生成內容幾乎免費,真正稀缺的變成了判斷力:哪個計劃是對的,該在哪一行停下來,哪個東西雖然能運行但從根本上就是錯的。迴圈不會貶低判斷力的價值——它剝離了一切不是判斷力的東西,只留下判斷力本身。

迴圈是一個忠實的放大器:

帶著理解力來——它會放大你的理解力。

帶著懶惰來——它會放大你的懶惰。

在你建立它之前,先決定好你想要放大什麼。

敬請期待!

祝你好運 :)

二次創作

使用 YouMind 創作爆款文章

收集素材、拆解爆點、生成視覺資產、撰寫內容,並在一個 AI 工作空間裡完成分發。

了解 YouMind
寫給創作者

把你的 Markdown 變成乾淨的 𝕏 文章

圖片上傳、表格、程式碼區塊,往 𝕏 上手動重排太痛苦。YouMind 把整篇 Markdown 一鍵轉成乾淨、可直接發佈的 𝕏 文章草稿。

試試 Markdown 轉 𝕏

更多可拆解樣本

近期爆款文章

探索更多爆款文章