跳到主要內容

【2026 最新】OMP A/B 測試:Plan、Advisor、Reviewer 為什麼又慢又燒 Token?

最後更新: ·
OMP Plan、Advisor、Reviewer 四組 A/B 測試教學首圖

同一個 coding-agent 任務,為什麼 OMP 有時做得更久、Token 也更多?真正要拆的不是「OMP 快不快」,而是三筆不同的保險費:Plan Mode 在動工前規劃、Advisor 在施工中旁看、Reviewer 在完工後驗收。這篇 OMP A/B 測試教學會把它們拆成四組,同一題各跑 3 次,讓你用成功率、總時間與每次成功成本決定哪些角色值得開。

截至 2026 年 9 月 21 日,OpenRouter 的 Oh My Pi 頁面顯示 1.35B Token、23 個使用模型;這只能證明有流量,不能證明品質,也看不出 Token 是主代理、Advisor 還是子代理花掉的。截至同日,本文查閱的 OMP 官方文件與公開 benchmark 中,未見四組同題、同模型的可重現消融結果。因此本文交付的是可重跑的實驗方法與判讀規則,不是一組假裝由本站跑出的漂亮數字。

OMP A/B 測試先記住:不要只比總 Token

總成本=主代理+規劃+即時顧問+事後審查+修正重工;每次成功成本=全部重跑成本 ÷ 通過驗收的次數。

  • 四組只能改一個流程變因;模型、Provider、thinking、工具、Repo commit、Prompt、整組超時與驗收都固定。
  • 每組 3 次只是抓明顯波動的冒煙測試,不是統計證明;要做團隊採購或預算決策,應擴成多任務、多次重跑。
  • 先看 Hidden Oracle 是否通過,再看 wall time、角色別 Token 與成本;失敗但便宜,不算省錢。
  • Advisor 預設可與主代理部分平行,Reviewer 則包含完成後的頂層審查編排與一個 reviewer 子代理;兩者不能用同一個「額外一次呼叫」概括。

如果你第一次做 Agent 評測,可先讀 SoL-Pi 四機制 A/B 教學理解「一次只改一項」,再用 Coding Agent 測試驗收方法設計不讓模型偷看到答案的 Oracle。

Plan、Advisor、Reviewer 到底多做了什麼?

依 OMP v18.2.6 CLI 文件Advisor 文件,三者發生在不同時間:

  • Plan Mode:--plan-yolo 先讓 plan 角色只讀探索並產生計畫,自動核准後才切到 --plan-yolo-into 指定的執行模型。它一定多一段規劃,但可能少走後面的冤枉路。
  • Advisor:另一個模型持續閱讀主代理新增的 transcript,必要時注入建議。它有自己的 Token 與成本;advisor.syncBacklog: off 時主代理不等它追上,但結束前仍可能等候最後的 review drain。
  • Reviewer:/review 在已有 diff 後啟動唯讀 reviewer。v18.2.6 的 headless prompt固定要求一個 reviewer task;它找問題,不直接改檔,所以若要比較最終品質,還要事先定義最多一次修正回合。

可以把它想成裝潢工程:Plan 是開工前的施工圖,Advisor 是施工中巡場的顧問,Reviewer 是交屋前的驗屋師。三個人都可能提早抓到錯誤,也都可能重複主代理已經做過的檢查。A/B 的目的不是證明「多一個人比較好」,而是確認那張施工圖、那次巡場或那場驗屋,是否真的少掉更昂貴的拆除重做。

OMP 預設、Plan only、Advisor only、Advisor 加 Reviewer 四組測試流程
四組都走同一個 Hidden Oracle;差別只在動工前、施工中、完工後是否增加一層檢查。

第一步:把版本、題目與答案鎖死

本文以 2026 年 9 月 18 日發布的 OMP v18.2.6 為基準,Bun 需 1.3.14 以上。安裝時不要追著 latest 跑:

bun --version
bun install -g @oh-my-pi/pi-coding-agent@18.2.6
omp --version

練習 fixture 可用公開的 p-limit commit a8a6fbe。每次 run 都從同一 commit 建立全新 worktree,先安裝一次相同依賴快照並確認原始測試通過,再交付這張任務卡:

這個 commit 要用 Node.js 20 以上,而且上游 .npmrc 關掉了 package lock。先在一份「fixture 母版」用 npm install --package-lock=true 產生 lockfile、跑完 npm test,再把 package-lock.json 記成自己的 benchmark base commit;12 個 worktree 全從這個本機 commit 分支,並在計時前各自執行 npm ci --package-lock=true。不要讓每個 arm 重新解析不同套件版本,也不要把安裝時間混進 Agent wall time。母版只能放程式與依賴,不能放答案、先前 session 或任何 run 產物。

替 p-limit 新增暫停/恢復能力:
1. pLimit 可接受 paused: boolean,預設 false。
2. limiter 暴露 isPaused、pause()、resume()。
3. pause 不取消執行中的工作,只阻止新的 queued task 啟動;resume 立刻依 concurrency 補滿。
4. limitFunction 也要轉交這些能力。
5. 更新型別、README 與公開測試,不改既有行為。
6. 完成後執行 npm test。

Oracle 由另一個人預先放在 Agent 看不到的目錄,至少測「暫停時 active task 可完成、pending task 不啟動」「多次 pause/resume 不重複執行」「改 concurrency 後 resume 仍守上限」「型別與 limitFunction 介面」以及禁改檔案。公開測試是施工者的尺,Hidden Oracle 才是裁判;這個觀念也適用於 spec-first 工作流比較

題目難度也要卡在「基準組有機會成功、但不是每次秒過」。若 A 組 3/3 都在幾秒內完成,Plan 與 Advisor 沒有發揮空間;若四組全數 timeout,則只證明題目或預算不合適。先用一個不列入統計的 pilot 檢查安裝、權限、Oracle 與 20 分鐘上限是否可用,正式 12 次才開始記分。

第二步:讓四個角色真的用同一個模型

不要只固定主代理。Reviewer 的 bundled agent 預設走 @slow,Advisor 走 modelRoles.advisor,Plan 走 modelRoles.plan;若三個 role 指向不同模型,你測到的是模型差異,不是角色差異。建立一份只供 benchmark 使用的 overlay,將 MODEL_ID 換成同一個完整 Provider/Model selector 與 reasoning level:

modelRoles:
  default: MODEL_ID:medium
  plan: MODEL_ID:medium
  advisor: MODEL_ID:medium
  slow: MODEL_ID:medium
retry:
  modelFallback: false
  fallbackChains:
    default: []
    plan: []
    advisor: []
    slow: []
tier:
  subagent: inherit
  advisor: inherit
advisor:
  enabled: false
  syncBacklog: off
  immuneTurns: 3
  maxNotesPerUpdate: 4

同時固定 service tier、thinking、context/output 上限、approval mode、啟用工具、MCP、LSP、rules 與記憶來源。每次 run 使用新的 session、worktree 與 prompt-cache key;金鑰只放環境變數,不寫進 task、config 或公開 log。想先理解 prompt cache 與重複上下文,可搭配 Claude Token 節省教學

這裡的「同一模型」還要包含同一個 Provider、同一 reasoning level 與同一 service tier。兩個平台即使顯示相同模型名稱,排隊、快取、價格與限流也可能不同。關掉模型 fallback 後,某次 429 或服務失敗就照原樣記成 infrastructure failure;不要讓 OMP 靜默換模型,再把較快或較慢的結果放進同一欄。

第三步:跑四組 OMP A/B 測試

先為每個 run 準備獨立的 WORKTREESESSION_DIRRUN.jsonl 與唯一 CACHE_KEY,並使用沒有舊 session、rules 或 WATCHDOG roster 的 benchmark profile。將下方 MODEL_ID 換成可用的完整 selector;TASK_FILE 必須是絕對路徑,避免 shell 在切換到 --cwd 前讀錯檔。四組都呼叫同一個 wrapper:

MODEL='MODEL_ID'
SERVICE_TIER='none'
CFG='/absolute/path/benchmark.yml'
TASK_FILE='/absolute/path/task.md'
TASK="$(cat "$TASK_FILE")"
RUN_ROOT='/absolute/path/omp-ab-runs'
IMPL_TOOLS='read,write,edit,bash,grep,glob,find,lsp,ast_grep,ast_edit,todo'

new_run() {
  RUN_ID="$1"                     # 例如 A-1、B-1、C-1、D-1
  RUN_DIR="$RUN_ROOT/$RUN_ID"
  SESSION_DIR="$RUN_DIR/sessions"
  CACHE_KEY="omp-ab-$RUN_ID-$(uuidgen)"
  ARM_DEADLINE=$(( $(date +%s) + 1200 ))
  mkdir -p "$RUN_DIR" "$SESSION_DIR"
}

run_omp() {
  local prompt="$1"
  shift
  local remaining=$(( ARM_DEADLINE - $(date +%s) ))
  (( remaining > 0 )) || return 124
  omp -p --mode json --profile omp-ab \
    --cwd "$WORKTREE" --config "$CFG" --session-dir "$SESSION_DIR" \
    --model "$MODEL" --thinking medium --service-tier "$SERVICE_TIER" \
    --approval-mode yolo --no-extensions --no-skills --no-rules \
    --tools "$IMPL_TOOLS" --max-time "${remaining}s" \
    --prompt-cache-key "$CACHE_KEY" "$@" -- "$prompt"
}

# A:預設;明確排除 task/eval/hub,避免暗中再開代理
new_run A-1
run_omp "$TASK" > "$RUN_DIR/events.jsonl" 2> "$RUN_DIR/stderr.log"
printf '%s\n' "$?" > "$RUN_DIR/exit-code.txt"

# B:Plan only;規劃與執行仍是同一模型
new_run B-1
run_omp "$TASK" --plan-yolo --plan-yolo-into "$MODEL" \
  > "$RUN_DIR/events.jsonl" 2> "$RUN_DIR/stderr.log"
printf '%s\n' "$?" > "$RUN_DIR/exit-code.txt"

# C:Advisor only;syncBacklog 維持 off
new_run C-1
run_omp "$TASK" --advisor > "$RUN_DIR/events.jsonl" 2> "$RUN_DIR/stderr.log"
printf '%s\n' "$?" > "$RUN_DIR/exit-code.txt"

# D:Advisor 完成後,直接送入 v18.2.6 官方 headless review 指令
new_run D-1
run_omp "$TASK" --advisor > "$RUN_DIR/main.jsonl" 2> "$RUN_DIR/main-stderr.log"
printf '%s\n' "$?" > "$RUN_DIR/main-exit-code.txt"
SESSION_DIR="$RUN_DIR/review-session"
CACHE_KEY="omp-ab-$RUN_ID-review-$(uuidgen)"
IMPL_TOOLS='task,read,bash,grep,glob,find,lsp,ast_grep'
run_omp 'Use task with agent: "reviewer" and a tasks array; create exactly 1 reviewer task for recent code changes. Return only provable P0-P3 findings and the verdict.' \
  > "$RUN_DIR/review.jsonl" 2> "$RUN_DIR/review-stderr.log"
printf '%s\n' "$?" > "$RUN_DIR/review-exit-code.txt"

上面不直接呼叫 /review,是因為 implementation arms 用 --no-extensions 排除環境差異;它等價重現 v18.2.6 headless prompt 的核心要求,明確要求 reviewer agent × 1。D 組若出現可信的 P0–P2,再把 findings 交給主代理修正一次並重跑測試;沒有 findings 就不追加回合。Reviewer 本身是唯讀,不能把「它指出問題」誤記成「成品已修好」;review 成本也包含頂層 orchestrator 與 reviewer 子代理,不是一個 model call。

D 組要合併 implementation session、review session 與修正回合的用量。--max-time 不保證包住最後的 Advisor drain,所以外層 CI/runner 還要在同一個 ARM_DEADLINE 強制結束整組;Plan、Reviewer 與修正都只能使用剩餘秒數。正式跑 3 輪時,先產生 A–D 的隨機順序,再把 RUN_ID 改成對應的 A-1…D-3,不要照範例的固定次序執行。

四組各跑 3 次,共 12 次,並在每個三次小區塊內打亂順序,避免 Provider 尖峰或快取暖機永遠偏向同一組。若第一輪只想做最低成本 smoke test,仍應保留全部失敗與 timeout,不能只挑最快的一次。這是 Agent Harness Token 效率分析最容易被忽略的一步。

OMP A/B 測試由品質守門、角色別成本到決策的評分卡
先用品質守門,再比較成本與時間;最後只保留在你的任務風險下有淨收益的角色。

第四步:記錄成功率、時間、Token 與重工

每次 run 完成後,先在 Agent 之外執行相同的公開測試、Hidden Oracle、git diff --check 與禁改範圍檢查。接著遞迴解析 $RUN_ROOT/$RUN_ID 下所有 session JSONL,並用 manifest 標出 implementation、review 與 repair phase;OMP 會把 Advisor 寫到 __advisor*.jsonl。不要用 profile-wide 的 omp stats --json 當單次帳本,因為它不接受任意 --session-dir 作為掃描目標。至少保留:

  • 品質:Oracle pass/fail、公開測試回歸、越界改檔、Reviewer 真/假陽性與最後是否修正。
  • 時間:主代理完成時間、全流程退出時間。Advisor 的非同步工作可能讓兩者不同。
  • 用量:依預先記錄的 phase/session 邊界,彙總 main、plan、advisor、review、repair 的 input、output 與 cache usage;reasoning Token 只有 Provider 有回報才記,缺值標 N/A
  • 重工:重試、失敗 edit、compaction、Advisor 被採納的 note、Reviewer 觸發的修正回合與工具呼叫數。

三次結果用中位數與範圍呈現,不要只報平均;成功率則保留 0/33/3。成本欄最重要的是「全部三次成本 ÷ 成功次數」:若某組花 6 美元只成功一次,每次成功成本就是 6 美元,而不是把兩次失敗刪掉後假裝很便宜。

若走 OAuth 或訂閱方案,OMP stats 顯示的美元值可能是 API 等值估算,不一定等於帳單;報告時要標成 estimate。真的要比較現金成本,改用同一個按量計費 API,並以 Provider usage/billing 紀錄對帳,不能把月費額度和 API 單價混算。

建議再加兩欄時間:primary settle 是主代理產出完成答覆的時點,process exit 是 OMP 完成 Advisor drain 並真正結束的時點。C、D 組若只記前者,會把最後仍在運作的第二模型藏起來;若只記後者,又看不出使用者何時已經拿到答案。兩欄一起報,才能分辨「等待變慢」與「背景成本增加」。

第五步:便宜模型分工要另開一輪

完成同模型消融後,才做實務上更省錢的 routing:例如主代理維持強模型、Plan 或 Advisor 改用較便宜模型、Reviewer 保留較強的 @slow。這一輪回答的是「怎麼配最划算」,不再回答「角色本身有沒有用」。仍沿用同一批 task、Oracle 與停止條件,並重新記錄錯誤建議率;便宜 Advisor 若頻繁誤判、讓主代理多做修正,低單價也可能換來更高的每次成功成本。

怎麼判讀:哪一種任務值得多付一層角色?

  • 低風險、需求清楚、Oracle 很強:先留在 A。基準組若穩定通過,額外角色多半只是在買重複檢查。
  • 跨檔案、需求有衝突、常在開工後改方向:看 B 是否降低重工與越界修改;Plan 的價值不是計畫寫得長,而是少返工。
  • 長任務容易遺漏限制或中途偏航:看 C 的 Advisor note 是否及時、正確且真的被採納。若多數是噪音,就先關掉。
  • 安全、付款、資料遷移或大 diff:看 D 的 Reviewer 是否抓到 Oracle 沒涵蓋的真問題;把修正時間與 Token 一起算進去。

若同一工具呼叫反覆 3 次仍沒有新證據、已用掉總時限 80%、Advisor 連續給出重複/互斥建議,或額外角色已使成本超過預算,立刻停止該 run、保留紀錄,回到 A 組最小配置。先完成這個因果測試,再做「便宜模型當 Advisor、強模型當 Reviewer」的第二階段經濟實驗;兩階段混在一起,就無法知道改善來自角色還是模型。

常見問題

1. Plan Mode 一定比較慢嗎?

它一定增加前置規劃,但總時間不一定增加;若計畫減少探索、錯改與返工,整體可能反而較短,只能靠同題重跑判斷。

2. Advisor 和 Reviewer 是同一個功能嗎?

不是。Advisor 在主代理執行中讀 transcript 並注入建議;Reviewer 在已有 diff 後做唯讀審查。

3. 可以用便宜模型當 Advisor 嗎?

可以,但先用同模型完成機制消融,再另做模型路由測試;否則無法分辨角色與模型品質的影響。

4. 每組跑 3 次夠嗎?

只夠做冒煙檢查。正式決策應增加不同風險與規模的任務,每個 cell 也要更多重跑並報告不確定性。

5. 為什麼不能只看 Token?

因為少做測試、提早放棄或輸出錯誤答案都會變省;品質守門後的每次成功成本才可比較。

6. Advisor 的 syncBacklog 要設多少?

主實驗固定 off,讓它不因等待策略混入額外變因;之後可另跑 1,測接近同步審查的品質/延遲交換。

7. Reviewer 找到問題就算成功嗎?

不算。它不直接改檔;要確認 finding 為真、完成修正並重新通過 Oracle,才可算進最終成功。

8. 什麼時候應回到最小配置?

當 A 組已穩定通過、額外角色沒有提高成功率,或 Advisor/Reviewer 的真陽性價值低於等待與成本時,就關掉它們。可觀測、可回滾的 harness 才是重點;可延伸閱讀 AI Agent Harness 實作指南

結論:OMP 角色不是越多越安全

OMP A/B 測試真正要回答的不是「哪個角色最好」,而是它在你的任務風險下,有沒有用較少的失敗與重工,補回額外時間和 Token。先鎖定版本與 Oracle,跑 A;只有發現明確失敗型態,才依序加 Plan、Advisor 或完成後 Reviewer。若收益無法重現,就回到最小配置,把複雜度留給真的需要它的任務。

想繼續追蹤工具與方法,可瀏覽 AlphaLab AI 專區;若要把 Agent 評測、工作流與自動化系統化,也可查看 AlphaLab 課程

接著閱讀

左右滑動查看更多推薦

ALPHALAB 社群

有問題?來 Telegram 聊

和 Terry、編輯、其他網友一起討論這篇文章。提問、分享觀點,回覆更即時。

加入 Telegram 討論

📩 訂閱 AlphaLab 電子報

每週最多三封:一封 Weekly 週報與最多兩封關鍵 Alpha Signal。

我們不會 spam,隨時可退訂。