跳至主要內容

    Agent 駕馭工程懶人包 (6)|Ralph、Symphony、Cron 的外層迴圈差在哪?

    讓 agent 自己跑一整晚,進度存在哪、誰說它做完了?比較 shell 迴圈、看板排程與定時排程三種外層迴圈,整理 Geoffrey Huntley、OpenAI、Anthropic 與 Peter Steinberger 的做法,附對照表。

    sunny 桑尼· · 19 MIN READ · 212 次瀏覽

    Agent 駕馭工程懶人包 (6)|Ralph、Symphony、Cron 的外層迴圈差在哪?
    本文目錄

    讓 agent 自己跑一整晚,早上你會看到什麼?Geoffrey Huntley 是在個人部落格 ghuntley.com 寫作、提出 Ralph 技巧的開發者。他在 2025 年 7 月 14 日的文章裡貼了一位他教過的工程師的訊息(經對方同意):一份 5 萬美元的外包合約,用 Ralph 做出經過測試與審查的 MVP(最小可行產品),成本 297 美元。這是自述數字,沒有第三方驗證。

    包在單次 agent 執行外面、決定要不要再跑一輪的那一層,叫外層迴圈(outer loop);Cron 是 Unix 系統用固定時間表觸發工作的排程機制。這篇把 Ralph、OpenAI 的 Symphony、Peter Steinberger(開源 agent-scripts 儲存庫的作者)的做法和幾家的排程功能放進同一張表,比進度存在哪、什麼時候停、適合多大的規模。

    快速回答 外層迴圈的差別在三件事:進度存哪、誰判定停止、適合多大規模。Huntley 的 Ralph 把進度寫進檔案與 git,每輪重新啟動 agent,由人決定何時停;Symphony 依看板上的工單狀態繼續或停止,適合多個 agent 並行。Cron 類排程主要依時間觸發,只管何時開始,做完與否另靠檢查。任務有能自動驗證的終點,才適合讓迴圈自己停,並加上輪數上限;沒有的話,先留在對話裡做。

    圖 1 懶人包卡:外層迴圈四條結論。依據:Huntley 2025-07-14、OpenAI Symphony SPEC.md、Claude Code 文件(查閱於 2026-10-23)、steipete/agent-scripts 的 maintainer-orchestrator SKILL.md;歸納為本站整理。

    圖 1 的四條在下文各有一節:第 2 條見「Symphony 怎麼用看板排程?」,第 4 條見「Ralph 的停止條件是誰決定的?」。

    外層迴圈為什麼要把進度放到 context 外面?

    單次執行的 context(模型一次能讀的內容,有長度上限)會隨著重開或壓縮消失,所以每輪重開的外層迴圈(Ralph、Symphony、雲端排程)把進度存到檔案、git 或看板;沿用同一 session 的則靠對話加檔案。

    Huntley 把 Ralph 定義得很短:

    "In its purest form, Ralph is a Bash loop." 範例指令是 while :; do cat PROMPT.md | claude-code ; done。 (Geoffrey Huntley, Ralph Wiggum as a "software engineer", ghuntley.com, 2025-07-14)

    指令每轉一圈就重新啟動一次 claude-code,所以每一輪都從空白的 context 開始。他給的理由是 context window 可用的部分大約只有 170k tokens(原文:approximately 170k of context window),用得越多,結果越差。因此他要求一輪只做一件事(原文:One item per loop),並且每一輪都載入同樣的東西:計畫檔 fix_plan.md 和規格資料夾。模型每輪都要重讀這些,他承認這很浪費(原文:this is wasteful),因為每一輪都在重新耗用規格佔掉的額度;他仍然這樣做,是要每一輪都用同樣的方式配置 context(原文:deterministically allocate the stack the same way every loop)。

    工程上的意思: 進度放在 repo 裡,意味著迴圈的「記憶」可以被你讀、被你改、被 git 還原。Huntley 自己的用法就是這樣:他寫道,用 Ralph 做 CURSED 編譯器的過程中,多次刪掉整份 TODO 清單,再請 Ralph 重新產生一份。

    外層迴圈放在同一張表,進度、停止與規模差在哪?

    Ralph 和 Symphony 把進度放在 repo 或看板,靠人或工單狀態停;排程類只管何時開始,規模從單機 session 到多 agent 並行,詳見表 1。

    機制進度存哪怎麼停適用情境與規模

    Ralph(Huntley)
    進度存哪
    計畫檔、規格檔、git;每輪新 context
    怎麼停
    範例是無限 while;人盯著,必要時丟掉 TODO
    適用情境與規模
    他說最適合新專案,不會用在既有程式碼
    ralph-wiggum 外掛(Anthropic)
    進度存哪
    同一段對話(session);檔案與 git 留下上一輪成果
    怎麼停
    完成字串、輪數上限(預設無限)、手動取消
    適用情境與規模
    文件列為適用:目標清楚、成功標準明確
    Symphony(OpenAI)
    進度存哪
    工單在看板;排程器狀態只在記憶體
    怎麼停
    工單進終態或交接狀態才停;單次 session 上限 20 輪,之後續跑
    適用情境與規模
    預設同時最多 10 個 agent;官方稱預覽版
    Claude Code 的 /loop
    進度存哪
    開著的 session;排程任務存在該 session
    怎麼停
    你取消,或 Claude 判定做完;最多撐 7 天
    適用情境與規模
    單機單 session,最多 50 個排程任務
    Claude Code 雲端排程
    進度存哪
    雲端;每次新 clone 一份 repo
    怎麼停
    該次執行結束,下次時間到再跑
    適用情境與規模
    不必開機;最短間隔 1 小時
    Steinberger 的 maintainer-orchestrator
    進度存哪
    每個 repo 一條 Codex 執行緒;長期監看才寫日誌
    怎麼停
    排定的佇列清空;不自動續跑
    適用情境與規模
    多個 issue 或多個 repo 的佇列

    表 1 外層迴圈對照。來源:Huntley 2025-07-14;Anthropic ralph-wiggum README 與 Claude Code 文件〈Run prompts on a schedule〉(查閱於 2026-10-23);OpenAI Symphony SPEC.md;steipete/agent-scripts 的 maintainer-orchestrator SKILL.md(最後修改 2026-08-09)。欄位歸納為本站整理。

    Huntley 和 Anthropic 的外掛用同一個名字,機制卻不同:Huntley 的版本在 session 外面轉,外掛是用 Stop hook(在 Claude 想結束回應時攔截的自訂程式)把同一段 prompt 送回同一個 session。外掛文件寫得很清楚:這個迴圈發生在目前的 session 裡,不需要外部的 bash 迴圈,上一輪的成果靠修改過的檔案和 git 歷史留給下一輪。

    圖 2 誰觸發下一輪、進度存哪、怎麼停。依據:Huntley 2025-07-14、Symphony SPEC.md §2 與 §8、Claude Code 文件與 OpenAI 排程任務文件(查閱於 2026-10-23)。

    圖 2 畫的是 Huntley 的 Ralph、Symphony 與定時排程三條路線;外掛版的停止條件,在下一節說明。

    Ralph 的停止條件是誰決定的?

    Huntley 的 Ralph 靠人看著進度決定何時停;Anthropic 的外掛加了完成字串和輪數上限,但「做完了」仍由 worker(負責執行任務的模型)自己說。

    Huntley 的文章裡沒有給停止條件。他寫的是,Ralph 遲早會把 TODO 清單做完,或者「完全跑偏」(原文:it goes completely off track);這時由他決定要不要把清單丟掉重建。換句話說,監看的人就是停止條件。

    Anthropic 的 ralph-wiggum 外掛把這件事寫成參數:

    • --completion-promise:模型輸出指定字串(例如 <promise>COMPLETE</promise>)時迴圈結束。文件說比對是精確字串,無法用來表達多個完成條件。
    • --max-iterations:輪數上限,預設無限。文件把它當安全網,要求一律設定。
    • /cancel-ralph:手動取消。

    這三者裡,只有完成字串在判斷「做完了沒」,而它是 worker 自己輸出的。文件列出的不適用情境是:需要人類判斷或設計決策的任務、成功標準不清楚的任務,以及 production 除錯。

    Claude Code 另有一條路線:/goal。你寫下一個完成條件,每一輪結束後,由一個小型快速模型讀對話紀錄判斷條件是否成立;文件的說法是,完成由一個全新的模型判定,與 worker 分開。這個評估模型不執行指令、不讀檔案,只能判斷 Claude 已經在對話裡呈現的內容。條件成立、被判定不可能達成,或出現需要你處理的錯誤時,目標會清除。要限制長度,文件建議在條件裡加一句,例如「或在 20 輪後停止」。

    工程上的意思: 停止條件的位置,決定了誰能被騙。完成字串放在 worker 手上,它說「完成」就結束;/goal 把判斷交給另一個模型,但那個模型只看得到對話裡的證據。文件的建議是把條件寫成 Claude 的輸出一定會露出來的東西,例如「npm test 結束碼為 0」,評估才有東西可讀。

    Symphony 怎麼用看板排程?

    Symphony 依任務看板上的工單狀態排程:它定期查詢看板,替每張進行中的工單開一個隔離的工作區並啟動 agent,工單進入終態或交接狀態(例如 Human Review)才停。

    OpenAI 在 openai/symphony 的 README 把它描述成讓 agent 在隔離環境中自主完成實作,並標示為給受信任環境測試的「低調工程預覽版」(原文:a low-key engineering preview for testing in trusted environments)。它也寫明這個專案在已經採用駕馭工程的程式碼庫上效果最好(原文:works best in codebases that have adopted harness engineering)。

    排程細節在 SPEC.md,本篇查閱的是 2026-10-23 的 main 分支:

    項目預設值作用

    輪詢間隔
    預設值
    30 秒
    作用
    多久看一次看板
    同時執行的 agent
    預設值
    10 個
    作用
    全域併發上限
    單次 session 輪數
    預設值
    20 輪
    作用
    每輪結束重查工單,仍進行中才繼續
    正常結束後續跑
    預設值
    1 秒
    作用
    正常結束且工單仍在進行中時排入下一次
    失敗重試
    預設值
    10 秒起,逐次拉長(指數退避)
    作用
    上限預設 5 分鐘
    停滯偵測
    預設值
    5 分鐘
    作用
    設為 0 以下則關閉

    表 2 Symphony 排程參數的預設值。來源:OpenAI Symphony SPEC.md §5.3、§8.4、§8.5(查閱於 2026-10-23)。

    每張工單有自己的工作區,跨次執行重複使用,成功也不刪除。工單進入終態,worker 停止並清理工作區;成功的 run 可以止於流程定義的交接狀態(例如 Human Review),不一定是 Done。

    進度存哪裡,SPEC 講得很直接:調度狀態「刻意放在記憶體」(原文:intentionally in-memory for scheduler state),不需要資料庫;重啟後靠看板與檔案系統復原,但重試計時器與進行中的 session 不會還原。SPEC 的待辦清單裡也列了「把重試佇列與 session metadata 存起來」。另外,工單的寫入(改狀態、留言、貼 PR 連結)通常由 coding agent 透過工具完成,Symphony 本身是排程器與看板讀取者。

    工程上的意思: 這個設計把「真相」放在看板。排程器掛掉,看板上的狀態還在,重啟就重新輪詢;代價是排程器自己的重試進度會遺失。

    Cron 與排程任務為什麼只管何時開始?

    排程功能主要由時間觸發,不管上一輪做完沒有;所以它只決定「何時開始」,是否做完要靠 prompt 內的檢查或另外的 /goal。

    Claude Code 文件把三種排程放在一張表比較(表 3)。

    方式在哪跑要開機或開 session最短間隔

    雲端排程
    在哪跑
    Anthropic 管理的雲端;每次新 clone
    要開機或開 session
    都不用
    最短間隔
    1 小時
    桌面排程
    在哪跑
    你的機器
    要開機或開 session
    機器要開;session 不用
    最短間隔
    表單 1 小時;Claude 設定時 1 分鐘
    /loop
    在哪跑
    你的機器
    要開機或開 session
    機器與 session 都要開
    最短間隔
    1 分鐘

    表 3 Claude Code 的三種排程。來源:Claude Code 文件〈Run prompts on a schedule〉(查閱於 2026-10-23)。

    表 3 裡的 /loop 還有四條限制:

    • 任務在 session 閒置時才觸發,插在兩個 turn 之間;若 session 忙碌時錯過了觸發,文件說只在閒下來時補一次,不會把錯過的每次都補上。
    • 週期任務建立 7 天後自動過期;一個 session 最多 50 個任務。
    • 週期任務會被加上延遲(jitter),最多是間隔的一半、上限 30 分鐘;*/5 * * * * 不延後,反而提早 15 秒(文件寫的是每 5 分鐘的任務在上一輪後 4 分 45 秒觸發)。
    • 省略間隔時,Claude 自己選,每次在 1 分鐘到 1 小時之間挑;它判定做完時可以停掉自己。

    OpenAI 的排程任務文件(原 Codex app automations 網址,現轉址到 learn.chatgpt.com)分成兩類:獨立的排程任務每次執行都開新的對話;對話內的排程任務則回到同一個對話、帶著原本的 context。Git 專案可以選本機或新的 worktree(獨立的工作目錄);文件警告,本機模式可能改到你正在編輯的檔案,需要本機檔案時電腦要開著、app 要在執行。進階排程用 RRULE(iCalendar 的週期規則)設定,文件中沒有提到 cron 語法。

    工程上的意思: 排程功能要先回答的,是「每次醒來要不要記得上次」。這跟 Ralph 的選擇是同一題。

    Steinberger 與 Latent Space 怎麼看迴圈疊在一起?

    兩方都把外層迴圈視為可以疊加的層:Steinberger 設了具體的閘門,規定何時啟動、併入前要過哪些檢查;Latent Space 給的是疊加的方向。

    Peter Steinberger 是開發者,在 GitHub 以 steipete 發表 agent-scripts 儲存庫。Latent Space 的 AINews 在 2026 年 6 月 12 日引用了他的貼文:

    "Here's your monthly reminder that you shouldn't be prompting coding agents anymore. You should be designing loops that prompt your agents." (Peter Steinberger, 引自 Latent Space, Loopcraft: The Art of Stacking Loops, 2026-06-12)

    他在 agent-scripts 裡的 maintainer-orchestrator skill(2026-08-09 最後修改)可以看成這句話的實作(skill 本身沒有引用那則貼文,這是本站的詮釋),和排程直接有關的條文見表 4。

    項目skill 的條文

    啟動條件
    單一 issue 或 PR 不啟動;持續維護才建 heartbeat
    worker 階層
    根協調者加每個 repo 一個 worker;worker 不能再建 worker
    分流
    分成可自主處理(Autonomous)、需要負責人決定(Needs owner)、不列入計畫(Not planned)三類
    需要人決定時
    一次只問一個,附完整說明與建議
    併入前
    repo 檢查、回歸測試、重新執行 autoreview(自動審查)且未發現問題、CI 全綠
    佇列清完
    不自動接新工作或發版,除非使用者要求持續維護

    表 4 maintainer-orchestrator skill 的排程相關條文(heartbeat 指週期性喚醒)。來源:steipete/agent-scripts 的 SKILL.md(最後修改 2026-08-09);欄位為本站整理。

    Latent Space 這篇出自 swyx(Shawn Wang)創辦的媒體,署名欄寫 "Latent Space",沒有列 swyx 個人。它引了 Andrej Karpathy(前 OpenAI 研究員、前 Tesla AI 負責人)談 Autoresearch 時說的話:「我不想當迴圈裡看結果的研究員,我是在拖慢系統。」(原文:I don't want to be the researcher in the loop looking at results etc, I'm holding the system back.)然後提出自己的看法:下個世紀的遊戲,是盡可能有效地把迴圈疊起來(原文:stack loops)。早期,知道何時往下退一層迴圈(為了可靠)有價值;但隨著模型進步,知道如何往上走一層迴圈(為了槓桿,也就是讓同樣的人力帶動更多 agent 工作)會更有價值。它還寫了一條「Salty Lesson」:不要自己動手修,把力氣放在能隨 agent 數量擴張的系統上,例如 goals(讓 agent 朝完成條件持續工作)和 orchestration(協調多個 agent)。

    各方哪裡一致,哪裡不同?

    Huntley、Symphony 和 Steinberger 的做法都把進度留在 repo 或看板,不同的是誰判定完成,以及適用多大的範圍。

    判定完成的有五種:Huntley 靠人盯,外掛靠 worker 自己輸出的字串,/goal 靠另一個模型讀對話,Symphony 靠工單狀態,Steinberger 靠測試、CI 加人。範圍的說法也不同:Huntley 說它最適合從零開始的新專案,他自己不會用在既有程式碼庫(原文:There's no way in heck would I use Ralph in an existing code base);Symphony 的 README 則說,在已採用駕馭工程的程式碼庫上效果最好。

    另一種解釋也說得通:迴圈變熱門,是因為單輪模型變強、能撐更長的任務,外層迴圈只是把原本由人按 Enter 的動作自動化。這和 Latent Space 說的「隨模型進步往上一層」相容。本文引用的來源沒有一份做過有無外層迴圈的對照實驗,無法排除這個解釋,也沒有第三方資料證實 Ralph 的 297 美元或 Symphony 的效益。

    從哪一種開始排?

    先看任務有沒有能自動驗證的驗收條件,再選迴圈。我的做法是這樣分:能自動驗證(測試通過、佇列清空、結束碼為 0),用 /goal 或 Ralph 類迴圈,並一律加上輪數上限;外掛文件要求一律設 --max-iterations,/goal 文件也建議在條件裡寫輪數或時間子句。不能自動驗證,先留在對話裡做,不要放進迴圈。需要一直開著、多條工作並行時,才考慮 Symphony 這類看板排程,前提是團隊的工單狀態已經能表達「進行中、交接、結束」。單純定時的檢查,用排程功能就夠,先決定每次要不要記得上次。這個順序沒有經過我自己的實測,只依上面各家文件排出。

    下一篇接著問:迴圈只是重跑同一套駕馭層,那駕馭層能不能依執行紀錄自己改進,各方怎麼說。

    常見問題

    Ralph 和 Claude Code 的 ralph-wiggum 外掛是同一個東西嗎?

    名字相同,機制不同。Huntley 的 Ralph 用 bash 迴圈每輪重新啟動 claude-code;Anthropic 的外掛用 Stop hook(攔截 Claude 結束回應的程式),把同一段 prompt 送回同一段對話。上一輪成果靠修改過的檔案和 git 歷史傳遞;外掛的輪數上限預設無限,文件要求另設上限作為安全網。

    /loop 和 /goal 差在哪裡?

    Claude Code 的 /loop 按時間排程,每隔一段時間再跑一次 prompt,要等 session 閒置時才會觸發。/goal 在每一輪結束後檢查條件:由另一個小型模型讀對話,條件成立、被判定不可能達成或出現需要你處理的錯誤時清除目標,否則繼續下一輪。前者決定何時開始,後者決定何時停。

    排程任務的 agent 會記得上一次做了什麼嗎?

    看設定。OpenAI 的獨立排程任務每次開新對話,對話內排程則回到同一個對話;Claude Code 的雲端排程每次新 clone 一份 repo。若每次都是新對話,才得靠檔案、看板或其他外部紀錄保留進度。

    迴圈沒有設停止條件會怎樣?

    看機制。Huntley 的範例是無限 while,ralph-wiggum 外掛的輪數上限也預設無限,都要自己設。Claude Code 的週期 /loop 任務 7 天後自動過期。Symphony 單次 session 預設最多 20 輪,真正的停止條件是工單進入終態或交接狀態。正常結束而工單仍在進行中時約 1 秒後續跑,失敗重試則從 10 秒起逐次拉長。

    延伸閱讀

    參考資料

    留言0

    登入後就能留言。

    登入