AI Workflow · part 19
[AI Agent] 從 41 分鐘到 73 秒:一張小工單的病理解剖
❯ cat --toc
TL;DR
同型工單從 41 分鐘、54 次工具呼叫,壓到 73 秒、5 次工具呼叫。近兩週 41 個 codex 執行紀錄拆開後量出一條公式:牆鐘時間約等於工具呼叫次數乘 14.3 秒,裡面約 9 秒是模型純思考。那張典型慢單裡,機器真正做事只有 4.4 分鐘,剩下九成是人為空窗跟自己回頭考古。四刀:模型換回 sol、思考檔位降到 medium、引用即內嵌寫死進工單模板、小工單豁免開場知識庫檢索。⚠️ 重跑量到的 tok/s 只有平常一半,原因是量測窗口不同,不算退化。

前言
請同事幫忙下樓買杯咖啡,結果他四十分鐘才回來——通常不是那家店真的很遠,是你只講了「去買咖啡」,沒說是哪一家、要哪一種,他還被規定逼著先讀完一整本員工手冊才准出門。
我們家那套派工架構,前陣子在同一個坑裡摔了一跤。只是同事換成 OpenAI Codex CLI,員工手冊換成每次啟動都要先跑一輪的知識庫檢索——一條「動工前先拿工單主題去翻內部筆記庫,確認有沒有前人經驗」的固定規矩,一輪就是好幾次工具呼叫起跳。立意良善,但對換個參數的小事來說純粹是稅。一張理論上簡單到不行的工單,跑出了 41 分鐘;拆開之後才發現,機器真正在做事的時間只有零頭,剩下的全部是可以避免的等待跟自己重新摸索。
只要你也在用 coding agent 派工,大概都遇過同一種煩:明明是件小事,交出去卻要等很久,而你說不清楚問題出在執行者身上,還是自己那張單寫得不夠好。這篇記的就是這趟解剖:怎麼找出真正拖慢的地方、修了哪四刀、以及同一類工單重跑之後量出的數字。
起:工程活外包給 codex,指揮官只留判斷
我們家的分工很直白:Claude Code 當「指揮官」,負責跟人對話、拍板方向、切工單、收工驗收——判斷這件事不下放。真正動手的工程活,像是建環境、跑一輪測試、批次改檔案,一律寫成一張自包含的「工單」,丟給 OpenAI Codex CLI 在背景跑。
工單是一個檔案:目標、步驟、驗收、紅線都寫在同一個地方,不用重講一次對話裡的來龍去脈。上面固定寫清楚四件事:目標(什麼算做完)、步驟(要做哪些事)、驗收(最好是機器自己就能核對的條件)、紅線(什麼東西碰都不准碰)。codex 拿到這張單自己在背景跑,不用人一直守在旁邊;旁邊另外掛一個看門狗,固定時間去查一下工單有沒有卡死——背景跑的東西卡住的時候,長得跟正在認真做事一模一樣,不主動去查永遠不會發現。
一張典型的小工單長這樣:
# 把 n-max 從 4 改成 5,重測 decode 速度
## 目標
換一個參數,量一個數字,回報結果。
## 步驟
1. 把服務旗標 --spec-draft-n-max 4 改成 5,重啟
2. 跑一發固定內容的速度探測
## 驗收(機器可判)
- 重啟後服務的 cmdline 含 --spec-draft-n-max 5
- 回報 decode tok/s(參考值:改之前是 47.5)
## 紅線
- 只動這一個旗標;失敗就回滾,不接著調別的
這樣切的理由很簡單:判斷貴,執行便宜。負責對話、裁決、寫規則的模型,額度要燒在「這個結果代表什麼」上才划算;讀檔、跑指令、寫結果這種機械性的活,交給便宜很多的執行模型去做就好,兩邊都燒貴的模型才是真的浪費。判斷這件事本身也沒辦法外包——查得多細、翻得多完整可以交給別人,但「這個結果代表什麼、該怎麼修」這個判斷,只有留在自己手上才算數。
這套分工已經跑了一陣子,怎麼寫工單、怎麼發射、怎麼驗收,細節記在系列前面那篇交辦 AI 工程任務。照理說已經很順——結果最近一張理論上超簡單的工單,還是把人坑了一次。
換一個參數重跑一次測試,聽起來連工單都不太需要認真寫。聽起來越小的單,越容易隨手打發成一兩句話:去把 X 改成 Y,測一下,好了跟我說。
是 codex 笨,還是工單的問題?
派給 codex 執行的小工單——像是換一個參數重新跑一次測試,單純到不能再單純——三不五時就跑到 40 分鐘以上。這速度合理嗎?一開始還真答不出來。
不知道是 codex 這個執行者本身就慢,還是自己寫的工單有問題、逼它繞了遠路。手上沒有數字,只有一種說不清楚的煩躁:同一件事,人自己動手可能十分鐘搞定,交給它卻要等上四十分鐘。
而且這種事不是只發生一次。同樣性質的小工單,一而再地卡在 40 分鐘上下,久到讓人開始懷疑,是不是自己對「小工單」的定義本身就有問題——會不會根本沒有「小工單」這回事,任何一張單交出去,都注定要付一筆看不見的固定成本?
拿最典型的一張慢單來解剖,代號 hina-nmax7-probe,帳面時長 41 分鐘。
機器只做了 4.4 分鐘的事:41 分鐘去哪了
沒有直接猜答案,是把近兩週累積的 41 個 codex 執行紀錄整批啃過一遍,合計 734 分鐘、3086 次工具呼叫(codex 每一次讀檔、跑指令、寫檔案的動作)。拆開之後,第一個浮出來的是一條公式:
牆鐘時間(人實際等待的時間)≈ 工具呼叫次數 × 14.3 秒,其中約 9 秒是模型純粹的思考底噪。
這條公式的意思是:每叫 codex 動一次手——讀一個檔、跑一條指令、寫一次結果——不管那個動作本身多快,前面都要先付一筆固定的思考稅。這 9 秒思考底噪來自模型動作前重新讀一次上下文、想一下該怎麼做,跟網路或磁碟無關;呼叫次數越多,這筆稅就收越多次。工具呼叫的次數,才是真正決定工單長短的變數——單一步驟做得快不快反而沒那麼重要。
順著這條公式往下查,還有兩個推翻直覺的結果。第一,把每條命令真正在跑的時間全部加起來,佔整體連四成都不到——而且這個數字還偏高,因為 codex 停在原地等遠端結果回來的那些時間,也記在「執行」頭上。第二,連線從頭到尾沒出過半次 timeout。換句話說,慢的原因不是網路,也不是機器算得慢,是別的地方在燒時間。

把 hina-nmax7-probe 這張典型慢單拆開,41 分鐘剛好分成三塊。第一塊是發射前的人為空窗,吃掉 19.6 分鐘——這段時間沒有任何東西在跑。第二塊 8.6 分鐘:因為上一張工單的成果沒有直接寫進這張票裡,codex 花了 9 次工具呼叫回頭去挖上一張票的日誌,等於自己重做了一次考古。剩下 13 分鐘才是有效工作,而其中機器真正在做事的,只有 4.4 分鐘。
一張帳面 41 分鐘的工單,機器真正動手的部分只佔了一成多,剩下九成是空檔和重工。
再往下比對快慢兩種工單,分水嶺很單純:工單裡的關鍵資料,是直接貼進去,還是只留一句話說「已經有了」。跑得快的工單(9 分鐘、35 次工具呼叫)會把旗標寫法、參考數值全部貼進正文;跑得慢的只寫一句引用,codex 就得自己去挖——挖的過程就是前面那 8.6 分鐘的重工。
這兩件事其實是同一件事:公式說每次工具呼叫都要付 14.3 秒,一句「證據已經有了」看起來省了幾個字,實際上是把找資料這件事拆成好幾次讀檔、好幾次翻日誌,每一次都要重新付一次思考稅。省下的字,換成的是好幾次工具呼叫的帳單。
四刀下去,同型工單只剩 73 秒
解剖過程裡,還順帶挖出一個跟速度沒有直接關係、但同樣值得記的漂移:目前用來跑這些工單的,是 gpt-5.6-luna 這顆模型,配上思考檔位(模型每動一步肯花多少力氣思考的設定)拉到最高的 max——等於用最便宜的模型配最貴的思考預算,不只貴,而且操作手冊寫的預設其實是另一顆模型 gpt-5.6-sol。設定跟規範早就對不上,只是沒人去對過。
解剖完,當場決定改四件事。
一,設定檔從 gpt-5.6-luna 改回 gpt-5.6-sol——luna 用起來的直接感受就是變笨了,而操作手冊寫的預設本來就是 sol,沒有留它的理由。二,思考檔位從 max 降到 medium,最貴的思考預算配最便宜的模型,本來就不成比例。三,「引用即內嵌」寫死進工單模板(每張工單開頭共用的固定骨架):只要提到數字、payload 或設定,一律貼原文,別只留一句「證據已經有了」叫對方回頭找。四,小工單可以跳過知識庫檢索:票上寫一句「本票豁免 KB 檢索」,開工就不用先跑那一輪。
前兩刀改的是設定,後兩刀是把規則寫死在模板裡——下一張工單不用重新學這次的教訓,模板已經逼著它照做。這也是一直在用的套路:規則靠人記得住,遲早會漏;規則一旦寫進模板、變成下一次自動觸發的條件,才真正算數。
這張表只看一件事:工具呼叫次數那一列,從 54 次砍到 5 次,牆鐘時間也跟著砍成不到零頭,砍掉的九成都是前面講的空窗跟考古。
| 指標 | 舊制 | 新制 |
|---|---|---|
| 牆鐘時間 | 41 分鐘 | 73 秒 |
| 工具呼叫次數 | 54(含 9 次考古) | 5 |
| 開場知識庫檢索 | 每次啟動必跑 | 0 次 |
| 使用模型 | luna + max | gpt-5.6-sol |
| 消耗 token | 未記錄 | 16,130 |
41 分鐘變 73 秒,不是估出來的改善,是同一類型工單原地重跑量出來的。16,130 個 token,對一張小工單來說不算貴——前提是工具呼叫次數真的壓得下來,思考稅這種固定成本省不掉,能省的只有次數。
最後只要記三件事。引用即內嵌:工單裡的資料是自己要備齊的功課,丟一句「已經有了」不算數,因為對方沒有的東西,它只能自己去找。別讓 AI 自己回頭考古:少一次翻舊日誌的來回,就是省下好幾次工具呼叫、好幾分鐘。執行者說完成不算完成:73 秒是重新發射同型工單量出來的,聽一句「改好了」不算數。
回頭看那杯咖啡的比喻:同事跑腿慢,通常不是他跑得慢,是沒把地址寫清楚。工單也一樣。
進階:解剖方法與那些沒寫進正文的發現
不讀這節不影響使用,主要是寫給以後要重跑這套解剖的自己看。
怎麼拆開 41 個 session。 一開始想過的做法是自己一行一行翻原始紀錄,很快發現行不通——3086 次工具呼叫,人工看不完,而且看的過程本身就會吃掉本來要省下來的時間,查得越細,反而越沒有餘力去問「這個結果代表什麼」。改成派一個唯讀的偵察分身,去讀兩批原始記錄:~/.codex-nomcp/sessions/2026/08/**/rollout-*.jsonl(每個 session 的完整動作記錄)加上 ~/.claude/tickets/*.log(工單本身的執行日誌),分身負責把原始紀錄嚼碎成看得懂的形狀,自己只看整理出來的數字,做最後判斷。公式量出來之後,拿另一張工單驗證:預計要打 54 次工具呼叫,套公式預測要跑 12.9 分鐘,實際跑出來是 13.0 分鐘,幾乎完全吻合。
原本以為是 codex 的問題,查完發現大半不是。 一開始的猜測是「這顆執行模型本身就慢」,查兩週份的紀錄下來,真正該算它錯的只有一例:一次單一空窗長達 97 分鐘,原因是 API 那端的生成卡住,只是個案,算不上通病。原本的預想錯在哪——把系統性的慢,誤判成執行者能力的問題,而系統性的慢其實藏在工單怎麼寫、怎麼發射這一層。這個誤判如果沒被拆穿,力氣大概會花在換一顆更貴的執行模型上,而不是去改工單怎麼寫——方向錯了,換模型也救不回那 8.6 分鐘的重工。
73 秒重跑那次,還差點誤判了一次退化。 重跑量到的推理速度是每秒 26.2 個 token,跟平常參考值每秒 47.5 個 token 比,像是掉了快一半。第一反應是懷疑哪裡退化了,查下去才發現是量測窗口不一樣——一個是冷啟動的短提示詞,一個是已經把 context 累積到 6.4 萬 token 的長跑測試,兩者本來就不該直接比。這條「量測窗口不同就不可比」的教訓才剛在前一天寫進操作手冊,結果同一個案例裡自己差點又踩了一次。留著這段是提醒自己,這條規則要真的變成直覺反應,不能只寫進文件就算數。
附帶發現三筆,跟這次的速度問題無關但值得記下來。 設定裡開的 nomcp(一個拿掉外掛工具的乾淨環境)其實沒有真的擋掉 MCP 工具,工具照樣能用,懷疑是外掛管道繞過去的,但還沒查證確定;看門狗的判定結果不會寫進檔案,事後要查就很費工;啟動時的日誌會被 > 這種寫入方式整份覆寫掉,前一次的紀錄留不住。三筆單獨看都不大,但性質相同——都是「設定寫了什麼」跟「系統實際在做什麼」兩件事悄悄對不上,而且對不上的時候不會有任何警訊,只能靠這種整批解剖才會被翻出來。三筆都排進了下一輪要修的清單。
常見問題
- 派給 AI 執行的小工單,為什麼常常跑得比想像中久?
- 多半不是模型算得慢,問題出在工單餵給它的資訊不夠。拆開近兩週 41 個執行紀錄後量到一條公式:牆鐘時間約等於工具呼叫次數乘 14.3 秒,其中約 9 秒是模型純思考。一張帳面 41 分鐘的工單,機器真正在讀檔、跑指令、寫結果的時間只有 4.4 分鐘,剩下九成是人為空窗跟自己回頭考古。
- 「時長約等於工具呼叫次數乘 14.3 秒」這條公式怎麼用?
- 派工前先估這張單大概要打幾次工具呼叫,乘上 14.3 秒換算成分鐘數當基準。實測驗證過:一張預計 54 次呼叫的工單,套公式預測 12.9 分鐘,實際跑出來是 13.0 分鐘。如果實際跑得比這個基準久很多,就該停下來查了。
- 「引用即內嵌」是什麼,為什麼要升格成硬規則?
- 工單裡只要提到任何數字、payload 或設定內容,一律把原文整段貼進去,別只留一句「證據已經有了」叫對方自己回頭找。這是拖慢那張 41 分鐘工單最重的一項病灶——codex 花了 9 次工具呼叫回頭挖上一張票的日誌,才把缺的資料補齊。
- codex 回報「做完了」,可以直接信嗎?
- 不能。獨立驗收要自己重新發射同型工單,量出新的牆鐘時間跟工具呼叫次數才算數,執行者自己講一句「改好了」不夠。73 秒的實證就是這樣量出來的。
接著讀
- 2026-07-17[Dev Workflow] 幫 AI agent 的 skill 減肥:193 個塞爆 2% 預算,砍到剩 7 個
AI Workflow 系列第 15 篇。某天早上我讀 codex 紀錄,滑到一行:skill 描述被剪短,才塞得進 2% 的 context 預算。我共用的 root 累到 193 個 skill,全載進去撐爆上限,每條描述都被截斷——我天天在用的,被剪掉是為了替我從不碰的一百多個騰位子。這篇講怎麼用 per-agent allowlist(不是刪)砍到 7 個、薄殼配深引擎壓低每個 skill 的載入成本,再用一個閘門加稽核加可逆退場區守住,不讓它肥回去。
- 2026-07-16[Dev Workflow] 一群 AI 交接工作卻不用重講:原來是同一套系統的兩條軸
這是 AI Workflow 系列裡『兩軸合流』這一段的收尾。回頭看整段路,前面六篇其實在蓋同一套系統的兩條軸:持久知識(我知道什麼,長效、要用再查)和即時狀態(我現在做到哪,易逝、隨時寫)。這篇講清楚兩條軸為什麼互不代替、怎麼匯流到『多 AI 交接』、又受同一套哲學管——以及那條讓一群不完全信任的模型還能安全協作的中心律:沒有收據就不信。
- 2026-07-12[Dev Workflow] 交辦 AI 工程任務:交出去的單位是一張工單檔,不是一段對話
交辦 AI 工程任務,交出去的不是一段對話,是一張工單檔。這篇講我怎麼把任務寫成自足工單(目標/步驟/機器可驗收/紅線)、detached 背景派工給 Codex、用三個 flag 和一個看門狗擋掉永久卡死,以及為什麼收到完工報告不等於做完——報告是 claim,驗收重跑才是 evidence。
- 2026-07-11[Dev Workflow] 額度斷在半路:讓 Claude Code 跟 Codex 交接任務的 handoff 協議
額度斷在任務半路,蒸發的不是知識庫,是這個任務的 live state:做到哪、排除了哪些死路、下一步跑哪個命令。這篇講我怎麼把 state 外部化成一個 handoff 檔,讓 Claude Code 跟 Codex 經 symlink 讀寫同一份、互相接手彼此做一半的活——以及用 hook 上鎖時踩到、又修掉的一個 false-takeover bug。
不想錯過新文章?
訂閱我確保不漏接!
隨時一鍵退訂。