從提示詞到一群替你工作的 Agent 的 14 步驟路線圖
大多數人建立的多步驟 Agent 最終都會變成一條直線。
第一步、第二步、第三步。每一步都客氣地等待前一步完成,才開始進行。
而且幾乎沒有人意識到,那些步驟中有一半根本不需要等待任何事情。
它們不會分流,不會分支,不會平行化。它們只是排隊。一個腦袋、一個上下文、一次做一件事,直到視窗塞滿,Agent 忘了自己在做什麼。
這就是 14 步驟路線圖,將那條單線隊伍轉變成一張圖。一張能擴展到整個 Agent 群、驗證自己的發現、並收斂出單一 Agent 無法維持的結果的圖。
到最後,你會知道三件事:
→ 你目前的系統在哪裡無謂地等待 → 如何分配工作而不失去對輸出的信任 → 如何在不影響品質的情況下降低費用
框架轉變,沒有人解釋過的那種
提示詞是一個句子。迴圈是一個循環。框架是 Agent 立足的基礎。
但工作本身的形狀——什麼先執行、什麼可以同時執行、什麼必須等待其他所有事情——那個形狀是 一張圖。
節點負責思考。邊負責傳輸結果。
而 Claude Code 已經提供了直接建立它們的工具:動態工作流程。
Claude 用純 JavaScript 寫一個編排腳本,然後啟動一個協調的 sub-agent 群來執行它。協調本身花費零 model token,因為它是程式碼,而不是對話。

路線圖分為四個區塊:
→ 01 到 04,看清你已有的圖 → 05 到 08,調動 Agent 群 → 09 到 11,信任產出的結果 → 12 到 14,確保它不會搞垮你
區塊 1 · 看清你已有的圖
01. 節點是任務,邊是流動的東西
一張圖只有兩樣東西,弄清楚它們就能解決幾乎所有混亂。
→ 節點:一個工作單位。一個 Agent、一個有邊界的任務、一個輸入、一個輸出。 → 邊:一個依賴關係。它表示這個節點的輸出會餵給那個節點的輸入。僅此而已。
錯誤在於把「然後」當作邊。
「總結這個檔案,然後告訴我天氣」在兩個部分之間沒有邊。天氣報告不會消耗摘要。它們是兩個不相關的節點,被一個線性腳本不必要地串在一起。
只有當資料實際傳遞時,邊才存在。

把它畫成方塊和箭頭。一個方塊就是一次對 agent() 的呼叫。一個箭頭就是一個變數,從一次呼叫的回傳值中出來,進入另一個的提示詞。
如果你畫不出箭頭,如果沒有變數傳遞,那兩個方塊就是獨立的。
而這種獨立性,就是你將在接下來的 13 個步驟中要利用的東西。
→ 規則:對於你 Agent 中的每一個「然後」,問問下一步是否會讀取前一步的輸出。如果不是,那等待就是浪費時間。
02. 你的線性腳本已經是一張圖,只是退化了
當你把一個 Agent 寫成「做 A,然後 B,然後 C,然後 D」時,你已經畫了一張圖。一條沒有分支的鏈。每個節點都只有一個輸入邊和一個輸出邊。
它運作得了。但它也跑得慢且脆弱,因為鏈沒有冗餘:如果 C 卡住了,D 就永遠不會發生,而 A 的工作就會被困在上游,無處可去。
圖工程的第一個真正技能是 重新繪製這條鏈。
拿你的線性 Agent,針對每一條箭頭,問問步驟 01 的那個問題。
大多數鏈都有兩三條不傳輸資料的箭頭。它們之所以存在,只是因為你當初輸入的順序就是那樣。
砍掉那些箭頭,鏈就會瓦解成更寬廣的東西:幾個可以同時執行的獨立節點,全部匯入一個真正需要它們的節點。
這不需要花錢,不需要新工具,而且通常能消除比你能買到的任何東西更多的等待時間。
→ 規則:在添加任何東西之前,先刪除那些不傳輸資料的邊。
03. 給每個節點一份合約
一個你無法推理的節點,就是一個你無法平行化的節點。
解決方案是一份合約:有邊界的輸入、有邊界的輸出、單一的工作。
→ 輸入是節點讀取的東西,明確傳遞,絕不假設來自共享視窗 → 輸出是定義好的形狀,最好經過驗證,這樣下一個節點就能直接使用,不用猜測

在工作流程中,這份合約是透過 schema 來強制執行的。當你傳給 Claude 一個帶有 JSON schema 的 agent() 呼叫時,sub-agent 被迫回傳有效的結構化資料。驗證發生在工具呼叫層,所以如果不符合,它會重試,而不是回傳自由文字讓你自行解析並祈禱結果正確。
1// 一個有真正合約的節點:有邊界的輸入、驗證過的輸出、單一工作2const ITEM = {3 type: 'object',4 additionalProperties: false,5 properties: {6 title: { type: 'string' },7 url: { type: 'string' },8 impact: { type: 'string', enum: ['high', 'medium', 'low'] },9 },10 required: ['title', 'url', 'impact'],11};1213const output = await agent(source.prompt, {14 label: `research:${source.key}`,15 schema: ITEM,16 agentType: 'general-purpose',17});
這就是一個能讓 Claude 接入圖中的節點,與一個只能讓人類閱讀的節點之間的區別。
→ 規則:如果一個節點的輸出沒有形狀,它就不是節點。它是一場對話。
04. 邊也是一份合約,而且是免費的
邊不是「B 在 A 之後」。它是一個關於傳遞內容的承諾:A 產生這個形狀,B 被設計來消費這個形狀。
當你根據資料而不是順序來命名邊時,兩件事就變得容易了:
→ 你可以立刻看出邊是否真實,因為你可以問是否有東西透過它流動 → 只要形狀維持不變,你就可以改變任一端點上的節點,而不會破壞圖
實際上,邊存在於純 JavaScript 中。在分流與綜合之間的中間步驟——扁平化、去重、過濾——只是對你節點回傳的形狀進行操作的程式碼。
那裡不需要 Agent。
而這就是以圖思考的其中一個隱藏勝利:人們花費大量 token 來支付的東西,實際上只是一個邊,而邊是免費的。
誘惑是啟動一個 Agent 來「合併結果」。抵制它。
如果合併意味著扁平化和去重,那就是一個 flatMap 和一個 Set。確定性、即時、零 token。
→ 規則:Agent 是為了判斷,而不是為了接線。一張每一條邊都是一個 Agent 的圖,就像是在為自己的線路繳房租。
區塊 2 · 調動 Agent 群
05. 用 parallel() 進行分流
這是能為其他所有事情買單的操作。
當你有 N 個獨立的節點、N 個要諮詢的來源、N 個要審查的檔案、N 條要稽核的路徑時,你不會把它們串起來。你會告訴 Claude 將它們分流並同時執行。
在工作流程中,這就是 parallel():它接受一個 thunk 陣列,為每個 thunk 啟動一個 sub-agent,全部同時執行,然後回傳結果陣列。

兩個細節讓它變得穩健:
→ parallel() 是一個屏障。它會等待所有 thunk 完成才回傳,所以下一階段會看到完整的集合。 → 一個拋出異常的 thunk 會解析為 null,而不是搞垮整個批次,所以一個不穩定的 Agent 不會搞砸執行。
這就是為什麼你總是對輸出使用 .filter(Boolean)。
併發數大致上受到核心數量的限制,多餘的會被排隊,所以你可以傳入一百個 thunk,它們都會完成,只是分批進行。
1phase('Research');23const raw = await parallel(4 SOURCES.map((f) => () =>5 agent(f.prompt, {6 label: `research:${f.key}`,7 phase: 'Research',8 schema: ITEM,9 agentType: 'general-purpose',10 }),11 ),12);1314const collected = raw.filter(Boolean); // 移除失敗 agent 產生的 null
這裡最重要的部分是:分流存在於 Claude 寫的程式碼中,而不是與模型的對話中。
Claude 自己的上下文永遠不會同時容納九個來源。每個 sub-agent 載入自己的來源,只有最終的回應會回傳。
這就是為什麼能擴展到數十或數百個 sub-agent 而不會淹沒 session。編排層花費零 token,因為它不是 Claude 思考的另一輪。
→ 規則:如果 N 個東西不會互相讀取,就不要排隊。將它們分流。
06. 在屏障處收攏分流
分流只有在有東西收集它時才有用。
匯入點是邊匯聚的節點。在那裡,一個 Agent 或一段程式碼,一次看到所有上游結果,並執行需要整個集合的事情:跨來源去重、按影響力排序、如果完全沒有任何回傳就提前退出。
這是唯一一個讓屏障在時鐘時間上值得其成本的地方。
跨所有來源去重?需要屏障,沒錯。
只是扁平化一個列表?那是邊,內聯處理就好。
1// 邊:純 JS,無 agent,零 token2const flat = collected.flatMap((c) => c.items);3log(`Collected ${flat.length} elements`);45phase('Curate');67// 屏障節點:需要整個集合來去重和排序8const curated = await agent(9 `Deduplicate and sort these by impact:10${JSON.stringify(flat)}`,11 { phase: 'Curate', schema: CURATED },12);
測試很簡單:如果你寫了 parallel → transform → parallel,而中間的轉換在元素之間沒有依賴關係,那你應該使用管線,並完全跳過屏障。
→ 規則:只有當一個階段真正需要所有之前的結果在一起時,才使用屏障。
07. 鑽石形狀:分割、處理、合併
結合分流與匯入,你就得到了任何嚴肅 Agent 圖的工作拓撲:鑽石形狀。
一個節點分割任務。許多節點平行處理。一個節點合併結果。

這種典型形式有一個值得記住的名字:分流 → 縮減 → 綜合。
→ 分流以獲得廣度 → 用純程式碼縮減以壓縮 → 用最終的 Agent 進行綜合以寫出回應
它是市場掃描、依賴稽核、程式碼審查和研究報告背後的骨架。你更換來源和提示詞,同一個骨架就能適應。
當你看到鑽石形狀時,你就不再問「我要如何讓我的 Agent 執行更多步驟」,而是開始問「哪裡是分割點,哪裡是合併點」。這才是真正能擴展的問題。
→ 規則:不要設計步驟。設計它在哪裡分割、在哪裡匯合。
08. 在執行時期對邊進行路由
並非所有圖都是固定的。有時候,要走的邊取決於節點發現的結果。
一個路由節點會檢查結果,並決定觸發哪條路徑。它對工單進行分類,並分支到正確的處理程式。它檢視 diff 的大小,並選擇快速審查還是啟動完整稽核。

在工作流程中,這是一個簡單的 JavaScript if 或 switch,基於節點驗證過的輸出,因為流程控制存在於程式碼中。
1// 路由節點:agent 進行分類,程式碼選擇邊2const { severity } = await agent(3 `Classify the risk of this diff:4${diff}`,5 { schema: {6 type: 'object',7 properties: { severity: { enum: ['low', 'high'] } },8 required: ['severity'],9 }},10);1112let review;13if (severity === 'high') {14 review = await parallel(FILES.map((a) => () => agent(`Audit ${a}`)));15} else {16 review = await agent(`Quick review of ${diff}`);17}
在這裡,確定性是一個功能,而不是一個限制。
路由器的決定可以來自 Claude,但路由是程式碼。對於相同的分類,它每次都以相同的方式執行。
節點中的模型判斷,邊中的腳本可靠性。不會出現「Agent 決定跳過稽核」這種意外,因為那個跳過必須寫在圖中。而它沒有。
→ 規則:讓模型決定這是什麼,讓程式碼決定要怎麼處理它。
反規則(繼續閱讀前請先看) 一張圖買到的是廣度。
它買不到更好的判斷力。
如果你工作的每一步都需要前一步的全貌,那麼將它分配給多個 Agent 並不會給你更好的答案。它只會給你相同的答案,更貴也更慢。圖開始發揮效益的時刻,正是工作分裂成彼此不讀取結果的任務的那一刻。在添加任何一個 Agent 之前,決定你帳單的唯一問題是:
我的工作在哪裡分裂?
如果它不分裂,堅持用一個 Agent,為自己省下接下來的 6 個步驟。
區塊 3 · 信任產出的結果
09. 在邊上放置一個驗證者
一張圖的真正槓桿不是擁有更多 Agent。而是你能圍繞它們建立的結構,以產生信任。
一個驗證節點位於邊上,在結果被允許往下傳遞之前。它的唯一工作就是嘗試推翻這個發現。如果發現存活下來,它就通過。如果沒有,它永遠不會到達答案。
而這背後有一個硬性規則:永遠不要讓同一個 Agent 批改自己的考卷。一個模型審查自己的輸出,會錯過大部分自己的錯誤,因為它是在與犯錯相同的位置進行評估。

三個值得記住的模式:
→ 對抗性驗證:針對每個發現,啟動 N 個獨立的懷疑者,命令他們反駁它。只有當它存活於多數時才保留。
→ 多元視角驗證:給每個驗證者一個不同的角度。正確、安全、可重現。多元性能捕捉到 N 個相同檢查永遠找不到的失敗模式。
→ 評審團:從不同角度產生 N 個嘗試,用平行的評審對它們打分,從勝者中綜合,並嫁接那些表現接近的答案中的最佳部分。
這就是一些用 Agent 完成的最雄心勃勃的專案背後的模式,例如移植整個執行環境,並將對抗性審查嵌入到迴圈本身中,而不是在最後才進行。
→ 規則:沒有發現可以不經驗證就傳遞,而且兩個驗證者永遠不會問相同的問題。
10. 隔離節點,讓失敗不會毒害整張圖
在一條鏈中,失敗會連鎖反應。C 死了,D 永遠不會執行,一切都停止。
在一張圖中,失敗應該被限制在它的節點內。
這已經部分實現了:一個在 parallel() 內部爆炸的 thunk 會解析為 null,所以八個好的 Agent 回傳結果,而壞的那個獨自倒下。你的 .filter(Boolean) 就是那個隔離措施。
設計每一個匯入點,使其能夠容忍缺失的輸入,而不是假設擁有完整集合。
最微妙的失敗是節點互相踩踏。當好幾個 Agent 平行寫入檔案時,它們會發生衝突。
解決方案是隔離:每個 Agent 在自己的 git worktree 中執行,在沙盒中完成工作,然後乾淨地合併。
只有在節點真正平行寫入時才訴諸這個方法。它是唯一需要它的拓撲的安全帶,而不是每個執行都預設要繳的稅。
→ 規則:每個檔案只有一個寫入者。而且每個匯入點都容忍空缺。
11. 添加一個迴圈,但要讓它收斂
有時候,你進入工作後才知道它有多大。未知規模的探索。一個錯誤掃描,發現一個錯誤會引出另外三個。
這就需要一個迴圈:一條回到前一個節點的可控邊。
危險顯而易見。一個不收斂的迴圈就是一個無限循環,不斷啟動 Agent 直到燒光你的預算。
能夠收斂的模式是 迴圈直到乾涸:持續啟動搜尋者,直到連續 K 輪都沒有產生任何新東西,然後停止。

而決定成敗的細節,幾乎所有人第一次都會犯的錯誤,是你針對什麼東西去重。
針對所有看過的內容去重,而不僅僅是已確認的內容。
否則,被拒絕的發現會每輪都重新出現,迴圈永遠不會乾涸,你就建立了一台機器,付錢讓它永遠重新發現同樣的死胡同。
1const seen = new Set();2const confirmed = [];3let dryRounds = 0;45while (dryRounds < 2) { // 2 輪空結果後停止6 const found = (await parallel(7 SEARCHERS.map((b) => () => agent(b.prompt, { schema: BUGS }))8 )).filter(Boolean).flatMap((r) => r.bugs);910 const newItems = found.filter((b) => !seen.has(key(b)));11 if (!newItems.length) { dryRounds++; continue; } // 沒有新東西 → 接近乾涸1213 dryRounds = 0;14 newItems.forEach((b) => seen.add(key(b))); // 針對「看過」去重,不是「已確認」1516 const judged = await parallel(newItems.map((b) => () =>17 parallel(['correct', 'security', 'repro'].map((lens) => () =>18 agent(`Judge "${b.desc}" from ${lens}. Is it real?`, { schema: VERDICT })))19 .then((v) => ({ b, real: v.filter(Boolean).filter((x) => x.real).length >= 2 }))20 ));2122 confirmed.push(...judged.filter((v) => v.real).map((v) => v.b));23}
→ 規則:每個迴圈都有一個輪數限制,並且針對所有看過的內容去重。
區塊 4 · 確保它不會搞垮你
12. 跨節點錯開模型
不是每個節點都需要你最好的模型。
一張圖讓這一點變得顯而易見,而單一 Agent 永遠做不到。有些節點是有限且重複的——提取這個欄位、分類這張工單。而有些節點則是真正判斷力所在的地方——綜合報告、裁定發現。
在無聊的節點上使用便宜的模型,把昂貴的 token 花在判斷力重要的地方。
在工作流程中,除非腳本覆寫,否則每個 sub-agent 會繼承你 session 的模型。預設情況下,一個大型執行完全按照你 session 的等級計費。
特定 agent() 呼叫中的 model 選項,只會將該節點路由到其他地方。
在大型執行前審查 /model,然後將重複的分流節點降級,同時保持融合節點使用高階模型。
這是一個槓桿,能將一個消耗大量 token 的圖變成經濟實惠的東西,而不需要改變它的形狀。
→ 規則:只有當判斷力攸關時,才使用昂貴的模型。
13. 拓撲就是你的成本和延遲
圖的形狀不是裝飾性的。它是影響時鐘時間的最大槓桿。
讓每個人都絆倒的決定:parallel() 與 pipeline()。
→ 一個 parallel() 屏障會讓所有東西等待最慢的節點完成,才能進入下一階段 → 一個 pipeline() 讓每個元素獨立地流經所有階段,沒有屏障。元素 A 可以在階段 3,而元素 B 仍在階段 1

快速的元素提早完成,而不是卡在慢的元素後面。
預設使用 pipeline。只有在一個階段真正需要所有之前的結果在一起時,才訴諸屏障:針對集合去重、基於總數提前退出、一個與「其他發現」進行比較的提示詞。
「看起來比較乾淨」和「階段感覺分開」不是理由。屏障延遲是真實的、可衡量的、浪費時間的。
分開不等於同步。
→ 規則:預設使用 pipeline,只有在有正當理由時才使用屏障。
14. 讓 Claude 畫圖
最後一步是,對於那些你無法預先規劃的工作,停止手動畫圖。
有了動態工作流程,你描述目標,Claude 自己編寫編排腳本:分解任務、選擇分流方式、啟動一個協調的 sub-agent 群,並綜合結果。
你得到一個針對該特定執行量身定做的圖,而不是一個你希望它能適用的固定圖。

有三個切入點:
→ 在你的提示詞中說出「workflow」這個詞,Claude 就會為這個任務寫一個 → 執行一個已儲存的或標準的。/deep-research 是一個在生產中執行的真實圖:綁定 → 平行搜尋 → 擷取 → 對抗性驗證 → 綜合。正是這個路線圖的骨架。 → 啟動一個模式,為 session 中的每個實質性任務規劃一個工作流程
當一個執行順利時,將它的腳本儲存在 .claude/workflows/ 中。有版本控制、可依名稱重新執行,並且任何克隆 repo 的人都可以啟動它。
› Launch a workflow that audits all routes in src/routes/ looking for
missing auth. One agent per route file, and verify each finding
before reporting it.
● Claude wrote an orchestration script · launching in background…
/workflows — auth-audit · running
✓ Bound 1/1 2.1k tok · 4s
✓ Fan-out 18/18 one agent per route file
◯ Verify 11/18 skeptics at 3 votes per finding…
○ Synthesize 0/1 waiting to verify
the session remains responsive, you can keep working while the fleet runs
→ 規則:如果工作的形狀在每次執行中都會改變,就不要畫圖。描述它。
本週可以建立的六張圖
對所有路由進行安全掃描。 每個路由檔案一個 sub-agent,每個都尋找遺失的權限檢查,接著是一個驗證環節,在每個發現到達報告之前確認它。單一上下文無法維持的廣度。
透過 /deep-research 取得附來源的報告。 Claude Code 內建的一張圖。它將你的問題分解成不同角度,平行執行搜尋,對來源去重,並在寫入前用三個投票的懷疑者對每個主張進行對抗性驗證。
逐檔案移植一個模組。 將翻譯工作分流到各檔案,測試套件作為每個檔案的關卡,失敗的檔案回到迴圈中。對抗性審查能捕捉到單次通過會交付損壞內容的情況。
對一個 diff 進行對抗性審查。 根據大小進行路由:小變更快速檢查,大變更觸發完整的平行稽核,審查者使用不同的視角——正確、安全、快速——然後由評審團進行綜合。
排程生態系統掃描。 儲存一次,永久重複執行。平行查詢許多來源——發行版本、部落格、論壇——在屏障處按影響力排序,並寫出摘要。版本化在 .claude/workflows/ 中,可依名稱啟動。
未知規模的探索。 你不知道有多少個錯誤。平行搜尋者,將每個新發現與所有看過的內容去重,驗證倖存者,迴圈持續直到兩輪都沒有產生任何東西。然後停止。
啟動你的第一張圖前的檢查清單
→ 我是否刪除了不傳輸資料的邊? → 工作是否真的能分裂,還是每一步都需要前一步的結果? → 每個節點是否有有邊界的輸入、有形狀的輸出,以及單一任務? → 我是否在為一個 flatMap 就能完成的事情付費給 Agent? → 是否有任何屏障不需要整個集合? → 是否有任何發現可以在沒有人嘗試推翻它的情況下到達結果? → 是否有兩個驗證者問相同的問題? → 所有迴圈是否都有輪數限制? → 是否有多個節點寫入同一個檔案? → 重複的節點是否正在使用昂貴的模型執行?
如果你超過三項失敗,你擁有的不是一張圖。你只是一個有更多步驟的鏈。
結論
提問提示詞的人問一個問題。設計架構的人畫一張圖。
線性 Agent 從來不是天花板。它只是第一種形式,每個人都會抓來用的那種,因為它符合我們書寫的方式。一行、一個腦袋、一次一件事。
當你開始看到節點和邊時,你不再要求 Agent 執行更多步驟,而是開始要求圖讓它變得更寬廣。
在工作獨立的地方分流。在信任重要的地方加上邊際關卡。在判斷力不是關鍵的地方使用更便宜的模型。
大多數人會繼續在單線隊伍中排隊。
那些學會畫圖的人,將會調動整個 Agent 群。而且他們永遠不會注意到其他人被困在其中的那個低矮天花板。
今晚就畫出你目前的系統。只要畫出任務和它們之間的箭頭。數數那些虛假的邊,然後刪除它們。
這是整個流程的第一步,零成本,而且通常比你能買到的任何工具都能消除更多的等待時間。





