想讓 AI 自己把事情做完、測試全過再叫你,結果它做到一半就停下來等你?這篇帶你從一行 while 開始,一步步做出會自己檢查成果的 loop!
你想把一件事整個交給 AI:把專案的依賴升到新版,測試全過再叫你,你先去開會。現在多半做不到。它做到一半就停下來問你下一步;就算一路做完,它回報「全部完成」,你還是得自己跑一次 pytest,才知道是不是真的。AI 寫得越快,這種等你確認的事就越多,你審不過來。
讓 AI 自己一輪一輪做下去、不用你每一步回應,這種做法今年有了名字:Loop Engineering。它的原理和 CI 很像:沒過就再跑一輪,過了才停。問題在「過了」由誰判定。AI 自己說的「完成」不能算數,你又不在場,就要有它以外的東西去看證據。
左邊是你現在的用法,右邊是 loop:中間交給兩個角色來回,worker 負責寫程式,reviewer 負責檢查它做完沒、做對沒。
我的判斷是:誰來判定做完了,決定 loop 能不能放著讓它跑。這篇用一個練習專案,從一行 while 開始,每一步解掉一個讓你得回來盯著的瓶頸,每一步都附設定檔、實際跑出來的畫面,和「怎樣算做對了」的檢查。
快速回答 Loop Engineering 是讓 AI 一輪一輪自己做下去,達到事先寫好的條件才停。能不能放著讓它跑,看誰判定做完了:寫程式的 AI(worker)自己說「完成」不算數。Claude Code 用
/goal寫終點,用 Stop hook 在 worker 想停時跑測試,沒過不准停;測試沒涵蓋的地方交給另一個 AI(reviewer)。每道檢查都要有上限,Anthropic 的團隊讓 reviewer 審到第三輪就重想做法。
開始之前:準備有 5 條測試的練習專案與 auto 模式,由客觀測試判定做完了沒
跟著做之前,先準備三樣東西。
一個有測試的小專案。這篇用的是一個叫 sales-report 的 Python 小專案:用 pandas 算每月營收、各區占比、各區平均,五條 pytest 測試。任務是把 pandas 從 1.5 升到 2。pandas 2 拿掉了 DataFrame.append 和 Series.iteritems,groupby().mean() 碰到文字欄位也不再默默略過、會直接報錯,所以一升上去測試就全紅。這是一個典型的依賴升級:有東西要修,修好沒有,測試說了算。report/summary.py 全文如下:
import pandas as pd
COLUMNS = ["region", "month", "amount"]
def load(rows):
df = pd.DataFrame(columns=COLUMNS)
for row in rows:
df = df.append(row, ignore_index=True)
df["amount"] = df["amount"].astype(int)
return df
def monthly_total(df):
return {month: int(total) for month, total in df.groupby("month")["amount"].sum().iteritems()}
def region_share(df):
totals = df.groupby("region")["amount"].sum()
return {region: round(value / totals.sum(), 3) for region, value in totals.iteritems()}
def average_by_region(df):
means = df.groupby("region").mean()
return {region: float(row["amount"]) for region, row in means.iterrows()}
def top_region(df):
totals = df.groupby("region")["amount"].sum()
return totals.idxmax()
tests/test_summary.py 準備了四筆銷售資料(台北、台中、高雄,2026 年 9 月和 10 月),五條測試分別檢查:筆數、每月合計、各區占比、各區平均、營收最高的地區。專案用 poetry 管理,測試指令是 poetry run pytest。你也可以用自己的專案,條件是有測試、在 git 裡、改壞了不心疼。
決定 AI 能做什麼。loop 要能自己跑,就不能每做一個動作都停下來問你。Claude Code 有幾種權限模式,這篇用到兩種:
claude -p 都可以- auto mode(2.1.283 版起是互動模式的預設;
--permission-mode auto) - 另一個模型代替你審每個動作
--dangerously-skip-permissions- 沒有人;官方文件寫明只能在隔離的容器或虛擬機裡用
Taichi 程式語言的作者、Meshy AI 創辦人胡渊鸣,在知乎寫過他怎麼一步步把 Claude Code 的產出拉高。他走到第二步就卡在權限:Claude Code「每十几秒就会问我各种权限问题」。他的解法是在 EC2 開一台機器,讓 Claude Code 在上面權限全開,順便提醒一句:記得寫一個每小時自動備份資料庫的功能,「別問我怎麼知道的」。這篇的畫面都在本機跑,所以用 auto mode。
看一次全貌。做完這篇,練習專案裡會多出這些檔案:
接下來每一步加一兩個檔案,加完就跑一次,看它擋住了什麼。下面的畫面都是 2026 年 10 月 20 日在這個專案實際跑出來的(Claude Code 2.1.303、Python 3.10、pandas 1.5.3 升 2.3.3)。截圖裡的指令比正文多兩個參數:--model sonnet 換成比較便宜的模型,--setting-sources project,local 略過示範機器上的個人設定;其他照正文。
第 1 步:一行 while 的 Ralph loop 停不下來,第 1 輪測試全過後仍會無限重跑且 Ctrl+C 殺不死
最短的 loop 是澳洲工程師 Geoffrey Huntley 在 2025 年 7 月公開的寫法,他叫它 Ralph(取自《辛普森家庭》的角色 Ralph Wiggum),原文只有一行:while :; do cat PROMPT.md | claude-code ; done。每一輪都從全新的對話開始,上一輪做了什麼,只留在檔案和 git 裡。
練習專案的 PROMPT.md 只有兩行,每一輪都餵同一份:
把這個專案的 pandas 從 1 升到 2,讓 poetry run pytest 全過。
做完後用一句話說你改了什麼。
把下面這段指令貼進終端機:它把原本的寫法換成現在 Claude Code 的指令,並印出輪數,方便看跑了幾輪。
# -p:不進對話畫面,做完這一輪就結束
# --allowedTools:-p 模式沒有人能按允許,沒列出來的動作會被拒絕
i=0; while :; do
i=$((i+1)); echo "=== 第 $i 輪 ==="
cat PROMPT.md | claude -p --allowedTools "Read,Edit,Bash"
done
-p 是非互動模式:讀進 prompt,做完就結束,回到 shell,while 再開一個全新的 claude。上一輪做了什麼,這一輪只能從檔案和 git 看出來。這一行把 Bash 整個開放給它,所以只在練習專案裡跑。
你猜它什麼時候會停?
它不會停。第 1 輪就把三個舊寫法改完、測試全過;第 2 輪讀到同一份 prompt,自己說「工作目錄裡已經有這次升級的改動,我沒有再動它們」,然後 loop 開第 3 輪。更麻煩的是 Ctrl+C:按下去只中斷當輪的 claude,畫面印出 Execution error,while 立刻開下一輪。要停,得關掉終端機,或另外 kill 掉那個 shell。
怎樣算做對了:看到第 2 輪以後的回報都是「已經做完了」,而 loop 還在跑。這一步的目的就是看它停不下來。
Anthropic 的 Justin Young 在 2025 年 11 月一篇談長任務 agent 的文章裡,記錄過 agent 自己做事時常見的毛病:還沒做完就宣告完成、沒有實際跑過就標成完成。這一行 while 一次撞到四個問題:
- 停不下來:它需要一個機器判得了的停止條件。
- 它說做完了,不一定做完:判定完成的是 worker 自己,需要一個和 worker 分開的 reviewer。
- 每一輪都從零開始:進度要寫在對話外面。
- 它能碰的東西沒有邊界:要先劃好它能碰什麼、錯了由什麼擋下。
這一年各家提出的做法,各自補上其中幾個。2025 年 9 月,Simon Willison 寫〈Designing agentic loops〉,提醒要放進沙箱、只挑成功標準清楚的任務;到了 2026 年 6 月,Addy Osmani 用〈Loop Engineering〉當標題,把誰觸發下一輪、什麼時候停、誰檢查、進度記在哪,合起來當成一件要設計的事。下面幾步照這四個問題,一個一個補。
第 2 步:進度寫在 PROGRESS.md 讓 4 輪修完自動停下,但判定做完的依然是 worker 自己
每一輪都是全新的對話,worker 不記得上一輪踩過什麼坑。所以進度要寫在 repo 裡,下一輪先讀。
胡渊鸣的做法是一份任務清單加一個啟動器:Claude Code 每次從清單拿一件事做,做完就結束,啟動器再開一個新的,直到清單空了。他給的 prompt 只有一句「干活;干完活退出」,「干活」是什麼,寫在 CLAUDE.md 裡。他還把規則和進度拆成兩個檔案:CLAUDE.md 很少改,因為「容易改坏掉」;經驗教訓讓 Claude Code 自己寫進 PROGRESS.md。
練習專案照這個做法,PROMPT.md 改成:
你在一個會重複執行的 loop 裡,每一輪都是全新的對話,上一輪的事你不記得。
1. 先讀 PROGRESS.md,看上一輪做到哪。
2. 只做下一件還沒完成的事,做完跑 poetry run pytest。
3. 把這一輪做了什麼、測試結果寫進 PROGRESS.md,然後 git commit。
4. 整個任務:把 pandas 從 1 升到 2,讓 poetry run pytest 全過。全部完成時,在 PROGRESS.md 最後一行單獨寫 DONE。
loop 把 while : 換成「PROGRESS.md 還沒寫 DONE」:
i=0; until grep -qx DONE PROGRESS.md; do
i=$((i+1)); echo "=== 第 $i 輪 ==="
cat PROMPT.md | claude -p --allowedTools "Read,Edit,Bash"
done; echo "loop 停了,共 $i 輪"
這次四輪就停了,而且一輪只修一處:第 1 輪只升版本,測試 5 個全紅,它把後面要修的三件事寫進 PROGRESS.md;第 2 輪修 append,剩 3 個紅;第 3 輪修 iteritems,剩 1 個;第 4 輪修 mean(),全過,寫下 DONE。每一輪的 worker 都不記得上一輪,接得上全靠那份檔案。
怎樣算做對了:git log 多了四個 commit,PROGRESS.md 裡每一輪都有一段紀錄,loop 自己結束,你沒有按 Ctrl+C。
它停了,停止條件是 grep,機器判得了。可是 DONE 是誰寫的?是 worker 自己。它說做完了,grep 就相信。這一步解掉的是「每一輪從零開始」和「停不下來」,判定做完的還是 worker。
第 3 步:用 /goal 讓獨立模型判定停止條件,但它只讀對話輸出、不會自己跑測試
要讓 worker 以外的東西來判,Claude Code 有一個現成的指令 /goal:你寫一個完成條件,它每一輪結束後交給另一個小模型判斷達成了沒,沒達成就自動開下一輪,不用你按 Enter。Codex 也有同名的功能。
條件怎麼寫,Claude Code 和 Codex 的官方指南要求幾乎一樣:
pyproject.toml 的 pandas 是 ^2poetry run pytest 結束碼是 0tests/ 裡的任何檔案「把專案升級好」是壞條件,判斷的模型沒有東西可以判。官方文件建議把輪數直接寫進條件,例如「or stop after 20 turns」。打開互動視窗(auto mode),輸入:
/goal pyproject.toml 的 pandas 升到 ^2,而且 poetry run pytest 結束碼是 0;不修改 tests/ 裡的任何檔案;最多 10 輪就停
設好之後它立刻開始做,不用另外下指令。一輪就達成了;按 Ctrl+O 打開詳細紀錄,可以看到判斷的模型為什麼認定做完了:
怎樣算做對了:看到 Goal achieved,按 Ctrl+O 讀得到理由;單獨輸入 /goal 會列出條件、跑了多久、判過幾輪、花了多少 token。要中途取消,輸入 /goal clear。
看理由裡的用詞:每一條都是「對話裡顯示了什麼」。官方文件寫得很清楚:判斷的模型不會自己跑指令、不會自己讀檔,只看對話裡出現過的東西。這次 worker 自己跑了 pytest、git status 和 git diff,輸出留在對話裡,判斷才有根據。worker 如果只說一句「測試都過了」,判斷的模型讀到的就只有這一句話。
第 4 步:掛上 Stop hook 讓測試腳本自己跑,測試沒過不准停且連擋 5 次後交回給人
要比 worker 的陳述更硬,就讓測試自己跑。Claude Code 的 Stop hook 是一支你掛在設定檔裡的腳本:worker 每次想停下來,腳本先跑;結束碼是 2,就不准停,寫到 stderr 的內容會交給 worker 當作繼續做的理由。上一步畫面裡的 running Stop hook,就是 /goal 在底下用的同一套機制,只是判斷的換成小模型。兩者的範圍也不同:/goal 只在當下的 session 有效;Stop hook 寫在專案設定裡,這個專案的每個 session 都會跑。
在專案的 .claude/settings.json 掛上這支腳本,順便加一條規則,不准 worker 改 tests/(第 5 步會用到):
{
"permissions": {
"deny": ["Edit(tests/**)"]
},
"hooks": {
"Stop": [
{
"hooks": [
{ "type": "command", "command": "python3 \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check_tests.py" }
]
}
]
}
}
腳本本身用 Python 寫,.claude/hooks/check_tests.py,只用到標準函式庫:
#!/usr/bin/env python3
"""Stop hook: Claude may stop only after the tests pass."""
import json
import os
import subprocess
import sys
from pathlib import Path
hook_input = json.load(sys.stdin)
counter = Path(os.environ["CLAUDE_PROJECT_DIR"]) / ".claude" / ".stop-blocks"
# stop_hook_active is true when this stop was already blocked once in a row
blocks = int(counter.read_text()) if hook_input.get("stop_hook_active") and counter.exists() else 0
result = subprocess.run(["poetry", "run", "pytest", "-q"], capture_output=True, text=True)
if result.returncode == 0:
sys.exit(0)
blocks += 1
counter.write_text(str(blocks))
if blocks > 5:
# blocked five times in a row and still red: hand it back to a person
print(json.dumps({"systemMessage": "Stop hook 連續擋了 5 次,測試還是沒過,交給人看。"}))
sys.exit(0)
tail = "\n".join(result.stdout.splitlines()[-15:])
print(f"pytest 還沒全過(連續第 {blocks} 次擋下),修好再停。最後 15 行輸出:\n{tail}", file=sys.stderr)
sys.exit(2)
記得 chmod +x,再輸入 /hooks 確認 Claude Code 讀到了:在清單的 Stop 底下選標著 [Project] 的那一條,詳細頁會寫 Source: Project settings (.claude/settings.json)。
腳本裡那個計數器,是停止條件的停止條件。Stop hook 如果一直擋,worker 會一直做下去。Claude Code 自己有一道保險:worker 沒有做任何動作、hook 卻連續擋了八次,就強制讓它停。官方文件建議讀輸入裡的 stop_hook_active 欄位,已經擋過一次就讓它停;那個做法擋一次就收手,適合提醒一下就好的 hook。這裡要的是測試沒過就繼續修,所以改成數次數:stop_hook_active 是 false,代表這是新的一次停下,計數歸零;連續擋滿五次,worker 第六次想停時測試還是沒過,就讓它停下來交給人。
試一次。這次不用 /goal,故意只叫它做一半:「只用 poetry add 把 pandas 升到 ^2,其他檔案先不要動,做完就停下來回報。」
worker 回報做完了,Stop hook 跑了測試,沒過,擋下。畫面上標的是 Stop hook error,這是 Claude Code 顯示結束碼 2 的方式,代表 hook 正常擋下,hook 本身沒有壞。
接下來發生的事更值得看。worker 查出原因是 report/summary.py 第 9 行的 df.append,但提示裡寫了「其他檔案先不要動」,它選擇聽人的,不改程式,回頭問人要「改」還是要「回退」。hook 一擋再擋,擋滿五次之後,worker 第六次想停,計數器生效,畫面印出「Stop hook 連續擋了 5 次,測試還是沒過,交給人看」,worker 停下來等人回覆。回它一個「改」,它把三處舊寫法改完、測試全過,這次 Stop hook 沒有再擋,它正常停下。
怎樣算做對了:故意讓測試不過時,看得到 Stop hook 擋下的訊息和測試的錯誤輸出;測試全過時,worker 停下來,hook 不出聲。這支腳本每次 worker 想停都會跑,所以測試要快,大專案只跑跟這次改動有關的那一組。
這次實跑也說明了為什麼一定要有上限。你給 worker 的指示,可能和 hook 的條件衝突;沒有上限,兩邊就會僵在那裡,一直燒 token。
第 5 步:reviewer 與 worker 角色分開,鎖定 tests/ 權限並讓獨立 subagent 審 diff
到這一步,判定做完的是測試。可是測試本身也可能被 worker 動手腳。worker 修不好的時候,最省事的路是改測試,讓它變成一定會過。我自己的專案裡就遇過:worker 補的測試,在功能根本沒跑的時候照樣會過,每一次都是 reviewer 抓到的。
先擋住最直接的那條路,就是上一步 settings.json 裡那條 "deny": ["Edit(tests/**)"]。如果寫成 Edit(...) 加 Write(...) 兩條,Claude Code 啟動時會直接提醒:Write(...) 不會被檔案權限檢查比對,只有 Edit(...) 規則會,而 Edit 規則涵蓋所有改檔的工具。
這一關要自己驗。故意叫它:「把 tests/test_summary.py 裡 test_top_region 的預期改成 "台中"。」
怎樣算做對了:改檔的動作顯示 Error editing file,git status 看不到 tests/ 有變動。
注意 worker 自己說的那句話:它「不會用 Bash 繞過去」。也就是說,繞得過去。這條規則只擋改檔工具,擋不住 shell。這次它選擇不繞,下一次不一定。要更硬,就在 CI 裡比對 tests/ 有沒有被改,或者再加一支 PreToolUse hook 檢查 Bash 指令。
擋住改測試檔,只擋得住明顯的作弊。程式碼改得對不對、有沒有漏掉的情況,要另一個角色去看。Anthropic 在 10 月公開了 Claude Code 團隊自己怎麼審程式碼,第一層就是這件事:PR 開出來之前,Claude 先自己跑測試、build、lint,再交給一個 subagent,用全新的 context 審這次的 diff。subagent 不會看到 worker 一路的對話,比較不會被 worker 的說法帶著走。
練習專案的 reviewer 放在 .claude/agents/reviewer.md:
---
name: reviewer
description: 審查這次的改動。寫 DONE 之前一定要先叫它。
tools: Read, Grep, Glob, Bash
---
你是 reviewer,只檢查,不改程式。
1. 跑 `git diff` 和 `git diff --cached`,只看這次還沒 commit 的改動;都沒有的話,看 `git show HEAD`。
2. 自己跑 `poetry run pytest -q`,把結果貼出來,不要相信別人說的「測試過了」。
3. 每個問題都要附檔案和行號;拿不出證據的不要寫。
4. 最後一行只寫 `VERDICT: PASS` 或 `VERDICT: FAIL`。
tools 裡沒有 Edit 和 Write,reviewer 用不了改檔工具;它還有 Bash,所以指示裡也寫明只檢查、不改程式。第 3 條來自 Anthropic 那篇文章給 code owner 的建議:審查規則要「cap the nits」,要求「a file and line as evidence instead of a guess」,少挑小毛病,每個問題都拿出檔案和行號,不要用猜的。
什麼時候叫 reviewer,寫在 CLAUDE.md,也就是胡渊鸣說的「干活」的規則:
# sales-report
## 干活的規則
- 每一輪先讀 PROGRESS.md,只做下一件還沒完成的事。
- 寫 DONE 之前,先叫 reviewer subagent 審這次的改動,拿到 `VERDICT: PASS` 才算數。
- reviewer 連續三次 FAIL:停下來,在 PROGRESS.md 寫下試過的做法和卡在哪,不要硬修。
- 進度和教訓寫進 PROGRESS.md;這個檔案(CLAUDE.md)不要改。
- 不准改 tests/ 底下的檔案。
reviewer 本身也需要停止條件。Anthropic 的文章寫了一個例子:一個 agent 寫、一個 agent 審,兩邊可以一直互相找事做,有一個 PR 一夜之間來回審、改了五十多輪,直到作者自己按停。他們回頭查,reviewer 一直標的東西,大約 59% 是第一輪就已經在的舊程式碼,後面幾輪多半在挑舊毛病。他們的對策是三輪之後,reviewer 要作者退一步,重新想做法;幾輪之後只審新的 diff;已經貼過的問題不再重複。改完之後,一輪就過的 PR 從 65% 升到 78%,要五輪以上的從 8.9% 降到 1.5%(Anthropic 自己公布的數字)。CLAUDE.md 第三條就是這個上限。但要分清楚:這條寫在 CLAUDE.md 裡,是給 worker 的指示,沒有腳本強制;硬性的上限只有 Stop hook 那一道。
第 6 步:用 stream-json 留存每輪日誌與 reviewer 報告,抓出測試沒涵蓋的行為改變
loop 跑通宵,早上你只看到結果。它中間卡在哪一輪、為什麼卡,claude -p 預設只印最後一句話,看不出來。
胡渊鸣寫了一個「管理 Claude Code 的 Claude Code」:一個 Python 程式負責派工,每件工作開一個 claude -p。一開始派出去的工作只有大約兩成真的做完。他把指令改成加上 --output-format stream-json --verbose,讓 manager 讀得到每一個動作的 JSON 紀錄,自己找出被管理的那個實例卡在哪。最後成功率到了將近九成五,他寫:「我也不知道怎么就成功率弄到几乎 95% 了」。
我很喜歡這篇文章,但這一句是我和他分開的地方。成功率從兩成變九成五,卻說不出是哪一步改好的;換一個專案,也沒辦法知道能不能重現。紀錄要存下來,才知道是哪一輪、哪一個動作出錯。練習專案照他的做法,把前面幾步收成一支 Python 的 loop.py,每一輪的紀錄存成一個 .jsonl,再印出摘要:
#!/usr/bin/env python3
"""One fresh Claude Code per round until PROGRESS.md ends with DONE, at most 10 rounds."""
import json
import subprocess
import sys
from pathlib import Path
MAX_ROUNDS = 10
progress, logs = Path("PROGRESS.md"), Path("logs")
logs.mkdir(exist_ok=True)
def done() -> bool:
return "DONE" in progress.read_text().splitlines()
def summarize(log: Path) -> None:
"""Print the tools this round used and how it ended."""
for line in log.read_text().splitlines():
event = json.loads(line)
if event["type"] == "assistant":
for block in event["message"]["content"]:
if block["type"] == "tool_use":
args = block["input"]
detail = args.get("command") or args.get("file_path") or args.get("subagent_type") or ""
print(f" {block['name']} {detail.splitlines()[0] if detail else ''}")
elif event["type"] == "result":
print(f" 結束:{event['subtype']},{event['num_turns']} 個 turn")
for i in range(1, MAX_ROUNDS + 1):
if done():
print(f"loop 停了,共 {i - 1} 輪")
sys.exit(0)
print(f"=== 第 {i} 輪 ===", flush=True)
log = logs / f"round-{i}.jsonl"
with open("PROMPT.md") as prompt, open(log, "w") as out:
subprocess.run(
["claude", "-p", "--model", "sonnet", "--permission-mode", "auto",
"--output-format", "stream-json", "--verbose"],
stdin=prompt, stdout=out,
)
summarize(log)
if done():
print(f"loop 停了,共 {MAX_ROUNDS} 輪")
else:
print(f"{MAX_ROUNDS} 輪還沒做完,停下來交給人")
sys.exit(1)
輪數上限寫在腳本裡,就算沒有人在旁邊,最多十輪也會停下來交給人。--model sonnet 是因為這種工作用不到最貴的模型。
摘要裡看得到 worker 照 CLAUDE.md 叫了 reviewer,reviewer 自己跑了 git diff 和 pytest;它交回的報告也存在紀錄裡,用 jq 就叫得出來。
測試全過,reviewer 判 PASS,但它多抓到一件測試沒涵蓋的事:原本的 load() 用 append 一筆一筆加,遇到 COLUMNS 以外的欄位會多出一欄;worker 改成 pd.DataFrame(list(rows), columns=COLUMNS) 之後,多的欄位會直接被丟掉。現在沒有程式依賴這點,所以不擋;可是測試沒寫到的這個行為改變,這次是 reviewer 抓到的。worker 也把這件事寫進了 PROGRESS.md。
怎樣算做對了:每一輪都有一個 .jsonl 檔,從裡面找得到用過的工具、被拒絕的指令和 reviewer 的報告,result 那一行看得到結束狀態。
第 7 步:用 git worktree 平行開工、/loop 定時巡檢,但合併與審查成本會隨分支增加
前六步都穩了,才值得往外擴。
同時跑幾個。胡渊鸣下一步是用 git worktree 開好幾個資料夾,每個資料夾跑一個 Claude Code:五個實例、每個大約五分鐘一個 commit,平均一分鐘就有一個 commit。Claude Code 現在可以直接用 claude -w <名字> 開一個新的 worktree。但平行縮短的只有寫程式那一段,合併和審查會跟著分支數變長,這部分在〈Multi-Agent Coding 是什麼?同時開很多個 Agent,真的會比較快嗎?(2026 完整解析)〉拆過。
定時跑。盯 PR、修 CI 這類工作,適合交給排程:
/loop/loop 5m 跑 poetry run pytest,失敗就修 report/,全過就用一句話回報- 你的電腦,視窗要開著
- 固定間隔的排程要請 Claude 取消,或 7 天後自動到期;不給間隔、讓 Claude 自己決定間隔的,按 Esc 就停;
.claude/loop.md可以寫預設指令
/schedule- Anthropic 的雲端,電腦關了也跑
- 最短間隔 1 小時;每次從乾淨的 clone 開始,讀不到你本機的檔案
怎樣算做對了:輸入 /loop 之後,畫面回報間隔和一個 8 個字元的 job ID;問它「我有哪些排程」,列得出這個 ID 和下一次執行時間。Stop hook 和 tests/ 的規則照樣有效,排程跑的每一輪都受同一套檢查。
人站在哪:依出錯風險分級審查,只有驗證便宜的維護工作才適合交給 loop
做完七步,最後一個問題是:人還要看什麼?
胡渊鸣的答案是幾乎不看。他的第十步是「坚持不去看除了 CLAUDE.md 以外的代码」,人該花時間的是把需求講清楚,「Context, not control」。這個答案有一個他自己講過的前提:那套軟體只給他一個人用,不用管多人登入、向前相容、穩定性,錯了也是他自己承擔。
Anthropic 的答案比較細。他們在 6 月到 9 月之間,合併的 PR 增加一倍以上,需要還原(revert)的比例降了四成以上(Anthropic 自己公布的數字)。人沒有退出,退出的是「每一行都要人讀」:
- 文件、文案、藏在 feature flag 後面的新增
- 自動檢查和安全審查全綠就不用人
- 一般產品改動;快取、自動更新、系統提示這類敏感區域
- 一個人
- 風險最高的程式碼
- 兩個人
風險等級由分類器看變更內容決定,不看是誰寫的。文章裡有兩句話值得抄進自己的規則:「An agent's approval never counts as a person's.」agent 的核准不算人的核准;「A person is accountable for every change that ships, whoever typed it.」不管誰打的字,每個上線的變更都有一個人負責。
張維峰在介紹這篇文章的短片最後,把它縮成個人明天就能做的三件事:寫一份短短的 CLAUDE.md,告訴 AI 怎麼檢查自己的成果;送出前先跑 /code-review,讓 AI 幫你挑一次錯;每次只改一小塊,出事才好退回。三件事剛好對到前面的 CLAUDE.md、reviewer,和錯了好還原。
兩個答案放在一起看,差別在出錯會傷到誰。只給自己用、出錯也只由自己承擔的工具,你可以選擇不逐行看;要交給別人、跑在正式環境的東西,loop 再自動,也要先寫好哪些改動要人看、看的人是誰。
哪些事先別交給 loop。Blake Crosley 整理過 Claude Code 負責人 Boris Cherny 公開的那些 loop,幾乎都是驗證便宜的維護工作:盯 PR、修 CI、整理使用者回饋。新功能要人看過才知道是不是想要的,架構好不好要幾個月後才看得出來,資料遷移做錯很難還原,這些先別交給 loop。連 Huntley 自己都說,他絕不會在既有的 codebase 上用 Ralph。
成本與安全。loop 會一直花 token:間隔要配合被盯的系統多久變一次,簡單的工作交給便宜的模型。無人看管的寫入權限會出事,Crosley 公開過自己的事故:自動建 worktree 的功能,刪掉了一個它沒建過的資料夾。沙箱、預算上限、每小時的備份,都比事後補救便宜。
結論:先定義誰判定做完了並設好停止條件,才把任務交給 loop 自動執行
開頭那個任務,依賴升到新版、測試全過再叫你,照這七步走完,就能交代下去。拆開來,每一步都在回答同一個問題:你不在場的時候,誰能說它錯。
/goal 的條件;pytest 結束碼;PROGRESS.md 的 DONEEdit(tests/**) 擋改檔工具,Bash 擋不住,要另在 CI 比對;危險動作由 auto mode 擋stream-json 紀錄工具會換,/goal、Stop hook 下個月可能又多一個新名字。這張表不會變:先寫好誰判定做完了,再讓它自己跑。
常見問題
Ralph loop 是什麼?
Geoffrey Huntley 在 2025 年 7 月公開的最短寫法:用 Bash 的 while 把同一份 PROMPT.md 一輪一輪餵給 coding agent,每一輪都從全新的對話開始,進度只留在檔案和 git 裡。原版沒有停止條件:用 while : 寫的話,任務做完了也會開下一輪,按 Ctrl+C 也只停得了當輪。改成讓 while 檢查進度檔裡有沒有寫 DONE,再加一個輪數上限,它就會自己停;但 DONE 是 worker 自己寫的,成果還要另外檢查。
Claude Code 的 /goal 和 Stop hook 差在哪?
/goal 由另一個小模型讀對話判斷做完沒,它不會自己跑指令,寫程式的 worker 說「測試都過了」,它讀到的就是這句話。Stop hook 是掛在 .claude/settings.json 的腳本,worker 每次想停,它就自己跑一次測試,結束碼回 2 就不准停。/goal 只在當前 session 有效,Stop hook 對專案裡每個 session 都有效。
兩個 AI 互相審查,會不會停不下來?
會。Anthropic 公開過一個 PR 一夜之間來回審、改了五十多輪的例子,reviewer 標的東西大約 59% 是第一輪就在的舊程式碼。他們的做法是三輪之後要作者退一步重想做法,之後只審新的 diff,已經貼過的問題不再重複。
什麼任務適合交給 loop?
驗證便宜、成功標準清楚的工作,例如盯 PR、修 CI,或有測試可跑、測試沒涵蓋的地方也有 reviewer 或人看的依賴升級。新功能、架構決定、資料遷移這類要人判斷或很難還原的工作,先別放著讓 loop 跑。
延伸閱讀
- AI 寫的測試全過,為什麼功能還是錯的?驗證閉環完整懶人包(2026)
- Claude Code 權限要怎麼設?一直按「允許」真的安全嗎?(2026 完整懶人包)
- Multi-Agent Coding 是什麼?同時開很多個 Agent,真的會比較快嗎?(2026 完整解析)
- GPT-6 Astra 能拿來做什麼?比一句話做遊戲更值得交給它的長任務(2026)
- AI 生產力悖論是什麼?為什麼 AI 做得更快,事情卻沒有更快交出去?(2026 完整解析)
參考資料
- Geoffrey Huntley, Ralph Wiggum as a "software engineer"(2025-07-14) https://ghuntley.com/ralph/
- 胡渊鸣,知乎專欄文章(2026 年初) https://zhuanlan.zhihu.com/p/2007147036185744607
- Addy Osmani, Morgan Westlee Lunt, Qing Wang (Anthropic), How the Claude Code team does code review(2026-10-15) https://claude.dev/blog/solving-code-review-at-anthropic/
- 張維峰(cooljerrett),介紹 Claude Code 團隊程式碼審查的 Instagram Reel(2026-10-18) https://www.instagram.com/reels/DenXZ96AzbE/
- Simon Willison, Designing agentic loops(2025-09-30) https://simonwillison.net/2025/Sep/30/designing-agentic-loops/
- Justin Young (Anthropic), Effective harnesses for long-running agents(2025-11-26) https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents
- Addy Osmani, Loop Engineering(2026-06-07) https://addyosmani.com/blog/loop-engineering/
- Blake Crosley, Loops win where verification is cheap(2026-06-09) https://blakecrosley.com/blog/loops-win-where-verification-is-cheap
- pandas, What's new in 2.0.0(DataFrame.append、Series.iteritems 移除;numeric_only 預設改為 False) https://pandas.pydata.org/docs/whatsnew/v2.0.0.html
- Anthropic, Claude Code docs:/goal、Hooks reference、Hooks guide、Subagents、Permission modes、Scheduled tasks https://code.claude.com/docs/en/goal https://code.claude.com/docs/en/hooks https://code.claude.com/docs/en/hooks-guide https://code.claude.com/docs/en/sub-agents https://code.claude.com/docs/en/permission-modes https://code.claude.com/docs/en/scheduled-tasks
- OpenAI, Using Goals in Codex https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex
留言0
登入後就能留言。
登入