最近在 X 和部落格上,常常看到 「Loop Engineering(迴圈工程)」 這個詞。
像是 「我已經不再對 Claude 下指令了,我的工作是寫迴圈」 之類,帶點幽默感的說法正在流傳
一開始我還想著:「又來一個新的『XX 工程』嗎……」
上下文工程 的書還在賣,harness 工程 也才剛看到不久
不過,這次有點不一樣。以往那些是在教你 「怎麼做好」,而迴圈工程說的是 「從你親自動手的位置上,乾脆退開」。

本文將依序介紹:
先快速掌握整體輪廓,深入的實作會放到後篇
內容以 2026/06 當下資訊為準。工具名稱、指令與支援版本很容易變動,最新資訊請以各官方文件為準
最常被引用的定義來自 Google Chrome 團隊的 Addy Osmani:
Loop engineering is replacing yourself as the person who prompts the agent. You design the system that does it instead.
大致翻成:「把你自己從『對代理下提示詞的人』的位置上移開,改為設計一套替你做這件事的系統。」
重點不是「怎麼把 prompt 寫得更好」,也不是「怎麼整理 context」,而是 把你這個人從那個位置上移開。
以前是工程師也要親自下場做事;接下來則是成為 設計工作流程的人。這就是角色的轉移。
如果把自己想成 團隊主管,就很容易理解。對成員事事微管理,團隊跑不起來;但如果 全丟出去不管,也跑不起來
好的主管要做的是,把目標、審查機制、交接流程設計好,讓自己不用逐一插手也能運作。

使用 AI 代理也是同樣道理,這就是迴圈工程
這個詞是在 2026 年 6 月幾乎同時出現並定型的:
Loop Engineering這三個人講的其實是同一件事:
你所設計的對象,已經從「代理的一次行為」,升級成「讓代理持續運轉的整個系統」。
迴圈工程和這兩年常聽到的各種「XX 工程」之間,其實不是互相取代,而是一層層堆上去。
每往上一層,負責的範圍就更大。
| 層級 | 管理重點 | 核心問題 |
|---|---|---|
| Prompt engineering | 單次指令 | 要對模型說什麼 |
| Context engineering | 這一刻視窗裡放什麼 | 要搜尋什麼、摘要什麼、丟掉什麼 |
| Harness engineering | 單次執行的「裝備」 | 允許哪些工具、以什麼算完成 |
| Loop engineering | 在 harness 之上自動循環 | 怎麼讓它自己反覆跑 |
我會覺得,迴圈就是比 harness 再高一層。
下層的 harness 是負責裝備 AI 代理的「一次執行」,上層的 loop 則是負責「讓它自動反覆執行」
所謂迴圈,不是「同一段程式一直空轉」的那種繞圈圈。
它每一輪都確實在做具體工作,拆開來就是 5 個動作。
| 動作 | 要做的事 |
|---|---|
| 發現(discovery) | 自己找出這一輪該做什麼 |
| 交接(handoff) | 將任務隔離後交給負責工作的代理 |
| 驗證(verification) | 由另一個代理檢查「這樣可以嗎」 |
| 持久化(persistence) | 把狀態寫到對話外部(例如檔案) |
| 排程(scheduling) | 透過 timer 等方式,讓它即使放著也能持續運作 |
我個人覺得,沒有驗證就不算迴圈。
如果這一塊太鬆,那就只是個不停生成內容的裝置而已
接著,若要把這 5 個動作真的做起來,就需要對應的工具。
落到開發層面,Addy 把迴圈需要的東西整理成 6 個零件。
| 零件 | 是什麼 | 對應動作 |
|---|---|---|
| Automations | 用時間表/觸發器自動啟動 | 排程 |
| Worktrees | 讓並行代理的工作目錄彼此隔離 | 交接 |
| Skills | 把知識固定在 SKILL.md 以便重用 |
發現 |
| Connectors(MCP) | 連接 issue tracker、DB、Slack 等外部系統 | 記憶 / 發現 |
| Sub-agents | 將生成角色與評估角色分開 | 驗證 |
| Memory | 留存在檔案中的狀態(例如 MEMORY.md) |
記憶 |
「只有檔案可見的迴圈」只能做很小的事;要能真正替你工作,得能碰到 任務票、資料庫、瀏覽器 才行。
把 MCP / Skills 想成迴圈用的 harness,會比較好理解
因為寫程式的人,最容易對自己的作品心軟。
就像自己寫的文章常常看不出錯字一樣,若讓作者自己打分數,很容易把自己說服成「看起來不錯」
所以要把 寫的人(生成角色) 和 檢查的人(評估角色) 分開,而且評估角色最好是另一套指令、甚至是另一個模型。
Claude Code 有一個 /goal,會持續跑到條件成立為止,完成判定是交給不是本人在做事的另一個模型。
其實 /goal 的內部實作,就是 基於 prompt 的 Stop hook。每一輪最後由判定角色檢查條件,沒過就不結束,再跑一輪——下一章我們就會手動做出這個東西

到這裡,相信大家對迴圈的概念都已經完全理解了。接下來就實際組一個能拿來做 coding 任務的迴圈吧。
第一個迴圈,只要把「完成的定義」和「無路可逃的檢查」交給 Claude Code 就夠了。
這裡我們會用 3 個檔案,做出一個把 coding 任務從「直線流程」變成「迴圈」的最小架構。
接下來會以你自己的專案來試作為前提。
預設目標是使用 React 或 Next.js、TypeScript 寫成的專案。

CLAUDE.md 寫入「迴圈協議」(=重新定義完成)在專案根目錄的 CLAUDE.md 中,寫下任務應該怎麼跑。
重點是 不要讓它自己宣稱完成
CLAUDE.md
## 迴圈協議
每個任務都要以「迴圈」而不是「直線流程」來執行:
1. 寫出修改
2. 跑檢查:測試 + linter + 型別檢查
3. 失敗了?讀取錯誤、找出原因、修正,然後回到第 2 步
4. 迴圈最多 5 次
停止條件:
- 全部檢查通過 → 回報「完成」,並附上通過的輸出作為證據
- 5 次用完 → 停下來,回報還剩下什麼沒解決
- 同一個錯誤連續出現 2 次 → 停止迴圈,並提示呼叫 @fixer
禁止:沒有檢查輸出就回報「完成」
禁止:透過刪除 assertion 或弱化測試來混過去。要修的是程式碼,不是分數板
最後那兩個「禁止」,其實是這個設定裡最有效的部分。
我曾經在沒加這個的情況下跑過,結果 Claude 在第 3 輪偷偷刪掉一行 assertion,把測試過掉了
。
測試是過了,但 bug 還在,而且看起來還很自然。只要把評估標準(停止條件)寫得不夠明確,迴圈就會毫不猶豫地鑽漏洞
.claude/settings.json 放入 hook就算在 CLAUDE.md 寫了規範,Claude 還是可能會忘記。
所以我們把 settings.json 裡的 hook 當成「硬性約束」。
每當 Claude 想停下來時,系統就強制跑檢查,並把結果塞回對話中。
.claude/settings.json
{
"hooks": {
"Stop": [{ "hooks": [{ "type": "command", "command": "npm test --silent 2>&1 | tail -20" }] }],
"PostToolUse": [{ "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "npx tsc --noEmit --pretty false 2>&1 | head -10" }] }]
}
}
這就是前面提到的 「/goal 的本體= Stop hook」 的自製版本。
Stop hook 負責扮演那個能說「不行」的評估角色,只要這一關沒過,迴圈就不能結束。
如果是 Python,就換成 pytest -q + pyright;Rust 則換成 cargo test --quiet + cargo check 即可
.claude/agents/fixer.md(用不同的上下文打破卡關)有些問題在同一段對話裡就是修不好。通常已經試了 4 次,context 裡充滿失敗 log,思路也被鎖死了。
這時候就把它交給 一個全新 context 的另一個代理。
.claude/agents/fixer.md
---
name: fixer
description: 用於同一個測試在兩次修正嘗試後仍失敗時,打破卡關的代理
tools: Read, Edit, Grep, Glob, Bash
model: opus
---
你要修正失敗的檢查。禁止猜測。
1. 自己執行失敗的檢查,讀完整個錯誤訊息
2. 從頭到尾讀完失敗路徑上的所有檔案
3. 用一句話寫出:真正原因是什麼
4. 只修那個原因,不做順手重構
5. 重新執行檢查,並回報修正前後的輸出
禁止:刪除測試、放寬 assertion、用 try/catch 吞掉錯誤、把測試 skip 掉
它是被主對話呼叫出來的,不帶著前面 4 次失敗的記憶,從零開始診斷,所以常常一次就能過。
這就是前面 6 個零件裡的 Sub-agents(將生成角色與評估角色分離) 本身。
把 CLAUDE.md 的協議、.claude/settings.json 的 hook、.claude/agents/fixer.md 的 fixer 放好,再把實際任務丟給 Claude 就行了。
一旦組好,反覆把終端機錯誤複製貼上重試的工作就消失了。
Claude 會自己跑、自己看、自己修,卡住時再叫出 fixer。
你最後只需要看一次 diff 就好

前面介紹的 Claude Code,是一個不需要新框架、就能 立刻在本機試用 的入口。接下來要談的是,把迴圈嵌進你自己的服務或工具裡來開發 的做法。
不需要從零自己寫迴圈骨架,框架裡已經內建了對應前面 /goal 的 Goals 功能,會持續跑到條件成立為止,並由另一個模型負責判定是否完成。
Goals 會把「持續存在的目標」綁在 thread 上,每一輪都由另一個判定角色(judge)模型評分,直到達成或達到上限為止。
src/mastra/worker.ts
import { Agent } from '@mastra/core/agent';
const worker = new Agent({
name: 'worker',
instructions: '把軟體任務完整做到最後',
model: 'openai/gpt-5.5',
memory, // 需要先接好 storage 的 memory
goal: {
judge: 'openai/gpt-5-mini', // 與作業角色不同的「判定角色」模型
maxRuns: 30, // 空轉上限(=成本上限)
prompt: '只有在測試通過時才視為完成',
},
});
// 為 thread 設定一個「持續存在的目標」(重新載入後也會保留)
await worker.setObjective('/health endpoint を追加してテストする', {
threadId,
resourceId,
});
judge(用與作業角色不同的模型來評分)和 maxRuns(空轉上限=成本上限)是兩個關鍵點。Claude Code 的 /goal 做的事情,幾乎就直接落到這兩個設定上了
Goals 是相對新的 experimental 功能(@mastra/[email protected] 新增),官方也明確說了未來可能會變動。最新參數請以官方文件為準。若停止條件是 能直接用程式碼判斷 True/False 的確定性條件,也可以考慮使用工作流程的 .dountil()。
方便歸方便,迴圈也有 放著不管就會默默累積代價 的一面。
A loop running unattended is also a loop making mistakes unattended.(沒有人看著的迴圈,也是會沒人看著地持續犯錯的迴圈)
大致有 4 個:
| 陷阱 | 症狀 | 一句防範方式 |
|---|---|---|
| 漏掉驗證 | 成果在累積,但沒人檢查 | 加入獨立於作業角色之外的評估角色(也就是 Stop hook) |
| 理解退化 | 程式碼越來越多,但腦中的地圖還停在舊版 | 定期閱讀輸出,確認自己是否還能說得清楚 |
| 放棄判斷 | 迴圈一跑起來,人就開始「算了啦」 | 可以交給系統執行,但不能把判斷也一起放掉 |
| token 暴衝 | 使用量劇烈波動,帳單難以預測 | 上線前先設定預算與最大重試次數的上限 |
特別是 token 暴衝,說白了就是錢的問題。
如果一個 bug 讓它整晚空轉,早上醒來時等著你的可能不是修好的程式碼,而是 陌生的帳單
與其說是節省成本,不如說是 避免事故。上線前務必設定硬性上限(單次預算、每日預算、最大重試次數)。前面 CLAUDE.md 裡的「最多 5 次」、「同樣錯誤出現 2 次就立刻停止」,也正是這類上限。
前面一直在說「迴圈要怎麼做」,最後來揭曉一個小彩蛋
這篇文章本身,就是用這裡介紹的迴圈寫出來的。 結構正好就是前面說的 6 個零件的最小版。
PROMPT.md(要寫什麼、文體、參考來源)= 發現MEMORY.md:記錄調查筆記與判斷 = 記憶老實說,這些評估角色真的把我盯得很緊。程式碼驗證角色說「Mastra 的範例這裡要再確認」,文體檢查角色說「用語比過去文章更硬」,最後連出處檢查角色都直接指出 「這個術語在參考來源裡沒有。是不是你自己亂掰的名字?」,抓出幻覺問題,讓我改了好幾輪
這正是 CLAUDE.md 裡那句「禁止:動分數板」的反過來,輪到我自己被修理了。
而我最有感的是這一句。Addy 結尾那段話真的很有力:
Build the loop. But build it like someone who intends to stay the engineer, not just the person who presses go.
把迴圈做起來吧。但要像一個打算繼續當工程師的人那樣去做,而不是只會按下啟動鈕的人。
迴圈可以讓生成變得近乎無限便宜,但 「要往哪個方向寫、要停止哪些產出」 這種判斷,還是無法被代勞。這篇文章也是一樣,比起評估角色的接線(工程),更有影響的是 把「什麼樣的文章算好」這個標準寫進 CLAUDE.md,再交給評估角色。
容器可以靠工程做出來,但裡面要放什麼樣的好壞標準,終究還是在做這件事的人心裡
有興趣的人,不妨先不要想得太複雜,照著本文的入門做法,在 CLAUDE.md 裡放入「迴圈協議」和 Stop hook,然後丟一個實際任務進去試試看。
你大概很快就會有種「啊,原來是這樣」的感覺