08 - Claude 當大腦、Codex 當雙手(核心架構)
← 07-Agent-Skill讓AI自己操控Herdr | 00-Index | 下一篇 → 09-實戰-刷題網站Taiwan-IM-board
⭐ 這是整份教學的核心章節。 前七章都是為了讓這一章能落地。
為什麼要這樣分工
你有兩個訂閱:Claude Pro 和 ChatGPT Plus。它們的特性不同:
| Claude Pro(Claude Code) | ChatGPT Plus(Codex CLI) | |
|---|---|---|
| 額度感受 | 較緊,長任務容易撞上限 | 較寬鬆,可以長時間跑 |
| 你已建立的資產 | 12 個 skill(note-orchestrator、neizhan-solver、google-med…)、PubMed MCP、兩個 repo 的 CLAUDE.md | 一般 coding agent |
| 強項 | 規劃、判斷、遵守複雜規則、醫學查證 | 大量、重複、規格明確的產出 |
所以最佳分工不是「誰比較強」,而是額度要花在刀口上:
Claude(貴、稀缺、懂規矩) → 想事情、切任務、驗收、commit
Codex(多、便宜、聽話) → 照規格幹活,一次好幾個
🔑 關鍵洞察:Claude Code 內建的 subagent(Task tool)也是燒 Claude 的額度。所以「用 subagent 平行處理」省的是時間,不是額度。 而 Herdr 開出去的 Codex pane 走的是完全不同的訂閱帳單——這才是真正的額度轉移。
架構圖
┌─────────────────────────────────────────────────────────────┐
│ Herdr Session (背景常駐 server) │
│ │
│ Workspace w1 "vault" │
│ └── Tab w1:t1 "agents" │
│ ├── Pane w1:p1 ★ Claude Code = 大腦 / orchestrator │
│ │ · 讀 CLAUDE.md、切任務、寫 prompt │
│ │ · 用 herdr CLI 開/餵/等/讀 底下的 worker │
│ │ · 查 PubMed、驗收醫學正確性 │
│ │ · 唯一一個負責 commit / push 的人 │
│ │ │
│ ├── Pane w1:p2 ○ codex "worker-a" ← 只寫檔 │
│ ├── Pane w1:p3 ○ codex "worker-b" ← 只寫檔 │
│ └── Pane w1:p4 ○ codex "worker-c" ← 只寫檔 │
│ │
│ └── Tab w1:t2 "validate" │
│ └── Pane w1:p5 □ shell(跑 validate.py / lint.py) │
└─────────────────────────────────────────────────────────────┘
↑ ↑
你的電腦(Windows Terminal → WSL) iPhone SSH 巡場
三條鐵律:
- Claude 是唯一的 commit 者。 Codex 只寫檔。(這也符合
Obsidian-med-note/CLAUDE.md§3「orchestrator 做唯一一次 commit」。) - Codex 不做需要事實查證的判斷。 沒有 PubMed MCP 的環境不准猜 PMID(
Obsidian-med-note/CLAUDE.md§4 已經明文規定)。 - Claude 驗收的依據是「檔案」,不是「agent 說它做完了」。 見 05-Agent偵測與狀態機制。
完整編排腳本(可直接用)
把這段存成 ~/bin/herdr-fanout.sh,Claude 可以直接呼叫它、也可以自己寫類似的:
#!/usr/bin/env bash
# herdr-fanout.sh — 開 N 個 codex worker,各自跑一個任務檔,等全部做完
# 用法:herdr-fanout.sh <任務目錄>
# 任務目錄裡每個 *.task.md 就是一個 worker 的 prompt
set -euo pipefail
TASK_DIR="${1:?需要任務目錄}"
: "${HERDR_ENV:?必須在 Herdr pane 裡執行}"
declare -a NAMES=()
i=0
for task in "$TASK_DIR"/*.task.md; do
i=$((i+1))
name="worker-$i"
# 1) 決定切的方向:前兩個往右,之後往下(避免切出細長條)
dir=$([ "$i" -le 2 ] && echo right || echo down)
# 2) 開背景 pane,保留目前工作目錄,不搶焦點
split=$(herdr pane split --current --direction "$dir" --cwd "$PWD" --no-focus)
pane=$(printf '%s\n' "$split" | jq -r '.result.pane.pane_id')
# 3) 啟動 codex(會等到它真的準備好才回傳)
herdr agent start "$name" --kind codex --pane "$pane"
# 4) 讓 sidebar 直接顯示它負責什麼
herdr pane report-metadata "$pane" \
--source user:fanout \
--display-agent "$(basename "$task" .task.md)" \
--token summary="$(basename "$task" .task.md)" \
--ttl-ms 86400000
# 5) 送任務(不等,讓它們平行跑)
herdr agent prompt "$name" "$(cat "$task")"
NAMES+=("$name")
done
echo "已派出 ${#NAMES[@]} 個 worker,開始等待……"
# 6) 逐一等待(總時限各自 30 分鐘)
for name in "${NAMES[@]}"; do
if herdr agent wait "$name" --until idle --until done --timeout 1800000 >/dev/null; then
echo "✅ $name 已 settle"
else
echo "⚠️ $name 逾時或出錯,請人工檢查"
fi
done
herdr notification show "fanout 完成" --body "${#NAMES[@]} 個 worker 已結束" --sound done幾個設計決定的理由
| 決定 | 理由 |
|---|---|
agent prompt 不加 --wait | 要平行。加了 --wait 就變成一個一個做 |
| 分開的等待迴圈 | agent wait 若現況已符合會立刻回傳,所以順序等待不會漏 |
--until idle --until done | 不接受 unknown——unknown 不代表完成 |
--timeout 給足 | 不給 timeout 會無限等 |
report-metadata | 讓 sidebar 顯示「誰在做哪批」,手機上巡場一眼就懂 |
| 用任務檔而非行內字串 | prompt 太長時 shell 引號會很痛苦;而且任務檔可以留下來 review |
驗收:不要相信狀態,要相信檔案
agent prompt --wait 或 agent wait 回來 不等於任務完成。原因在 05-Agent偵測與狀態機制 講過:
- Codex 是 screen manifest 偵測,狀態是「讀畫面猜的」
blocked偵測刻意嚴格,沒命中規則會退回idleagent prompt --wait追的是 lifecycle 狀態,不是單一 turn
所以驗收流程長這樣:
# ❌ 錯的驗收
herdr agent wait worker-a --until idle && echo "做完了!"
# ✅ 對的驗收:檢查它應該產生的東西
herdr agent wait worker-a --until idle --until done --timeout 1800000
# 1. 檔案存在嗎?
test -f tmp_drafts/114-心臟-001-012.json || { echo "沒產出"; exit 1; }
# 2. 內容通過機器驗證嗎?
herdr pane run w1:p5 "python3 tools/validate.py"
herdr pane wait-output w1:p5 --regex "PASS|FAIL|Error" --timeout 300000
herdr pane read w1:p5 --source recent-unwrapped --lines 60
# 3. 語意 / 醫學正確性 → 由 Claude 自己讀檔審(這步不能外包)💡 量產型任務天生適合這個模式,因為「產出檔案」本來就是任務本體。這同時繞開了 06-CLI與自動化基礎 講的 alternate screen 讀取限制——你根本不需要從畫面把長回應撈出來。
Prompt 怎麼寫(給 Codex 的任務檔範本)
Codex 拿不到 Claude 的 skill 和 CLAUDE.md 記憶,所有規格都要寫在任務檔裡:
# 任務:114 年心臟血管科 第 001–012 題 詳解草稿
## 你的角色
你是內科專科考試詳解的起草者。**只寫檔,不要 git commit、不要 git push。**
## 輸入
- 題目:`tmp_drafts/input/114-心臟-001-012.json`
- 撰寫規範:`docs/詳解撰寫規範.md`(**必讀,逐條遵守**)
- 品質標竿範例:`src/data/explanations.113.json` 裡的 `113-037`
## 輸出(唯一)
`tmp_drafts/out/114-心臟-001-012.json`
格式:`{ "114-001": { "text": "...", "status": "draft" }, ... }`
## 硬規則
1. 固定五段式:### 本題觀念 / ### 選項分析 / ### 答案解析 / ### 核心知識點 / ### 參考資料
2. **每一個選項都要分析**,指出錯誤選項是哪個概念的陷阱
3. `status` **一律 `draft`**,禁止寫成 `reviewed`
4. 正解依「該考試年度當時的標準」判定
5. ⚠️ **絕對禁止捏造 PMID / DOI / trial 數據。**
不確定的引用一律改成原則性描述,並在該處標 `[需查證]`。
(你沒有 PubMed 存取權,查證由審核者負責。)
6. 禁止罐頭字句:「此選項常是相近疾病」「供後續醫師逐題校閱」「以下為 AI 起草」
## 完成條件
輸出檔存在、是合法 JSON、包含全部 12 題、每題五段齊全。
做完只要回覆「DONE <檔案路徑>」,不要貼出全文。幾個關鍵設計:
- 「只寫檔,不 commit」 寫在最前面
[需查證]標記機制 —— Codex 沒有 PubMed,所以與其讓它猜,不如讓它明確標記出來給 Claude 收尾。這完全符合Obsidian-med-note/CLAUDE.md§4 的「不要猜 PMID → 明確告知待查證」- 「回覆 DONE + 路徑,不要貼全文」 —— 避免 alternate screen 撈長文的問題
常見踩雷(血淚整理)
1. agent start 失敗:pane 不在 shell prompt
agent start 要求 pane 停在互動 shell prompt——shell 自己擁有前景,沒有前景指令、編輯器或 agent 在跑。
如果你剛 pane run 了什麼東西還沒結束,agent start 就會失敗。先讓 pane 回到 prompt。
2. agent_prompt_stalled
agent prompt --wait 從非 working 狀態送出時,五秒內必須觀察到 lifecycle 變化,否則回這個錯。
常見原因:agent 其實還沒真的準備好、或者畫面偵測沒認出它動了。處理方式:
herdr agent get worker-a # 看目前狀態
herdr agent explain worker-a --verbose # 看偵測命中哪條規則
herdr agent read worker-a --source visible # 直接看畫面3. Codex 卡在 approval 但顯示 idle
blocked 偵測嚴格,Herdr 沒學過的新提示畫面會 fallback 到 idle。症狀是「wait 立刻回來但什麼都沒做」。
防禦做法:在等待迴圈之後,額外檢查產出檔案(見上面的驗收段)。真的常撞到就用 --source visible 讀畫面確認。
4. 忘了 --no-focus,畫面被搶走
背景工作一律加 --no-focus。這在你正在別的 pane 打字時特別重要。
5. 忘了 --cwd "$PWD"
不給 --cwd 時,新終端跟隨 terminal.new_cwd 政策(預設跟隨來源 pane / workspace)。在 worktree 情境下這可能不是你要的目錄。明確寫出來。
6. pane 被搬動後 ID 變了
pane move 跨 workspace 之後,pane ID 會變。用 .result.move_result.pane.pane_id。
而且已經在等待中的 agent wait 會以 agent_not_running 結束。
7. 一次開太多 pane,切成細長條
先 herdr pane layout 看形狀。超過 3–4 個 worker 時,改用「一個 worker 一個 tab」或「一個 worker 一個 workspace」,而不是一直切同一個 tab。
8. 多個 worker 改到同一個檔案
這是最貴的錯。解法是 git worktree:
herdr worktree create --cwd . --branch codex/worker-a --no-focus每個 worker 拿一個獨立 checkout,Claude 最後統一 merge。細節見 10-實戰-Obsidian醫學筆記庫。
什麼時候「不要」用這個架構
誠實列一下,免得過度工程:
| 情況 | 建議 |
|---|---|
| 任務 < 5 分鐘 | 直接讓 Claude 做完,開 pane 的成本更高 |
| 子任務彼此有依賴(B 要等 A 的結論) | 序列跑,或讓 Claude 自己做 |
| 需要 PubMed / 醫學事實查證 | Claude 自己做,不能外包 |
| 只有一個子任務 | 開一個 Codex pane 還是有意義(省 Claude 額度),但別為它寫 fanout 腳本 |
需要遵守大量 repo 慣例(CLAUDE.md 那些) | 慣例要完整寫進任務檔,否則 Codex 不會知道。規則太多太細時,Claude 自己做比較快 |
成本直覺(給你自己抓感覺)
一次「114 年某科 24 題詳解」的粗略分工:
| 工作 | 誰做 | 大概花費 |
|---|---|---|
讀 CLAUDE.md + 規範、切成 2 批任務檔 | Claude | 小(幾千 token) |
| 產出 24 題五段式詳解 | Codex ×2 | 大(Codex 額度) |
跑 validate.py、檢查 JSON 合法性 | shell pane | 幾乎零 |
| 逐題查證 PMID / guideline 年份 | Claude(+ PubMed) | 中 |
合併進 explanations.114.json、commit、push | Claude | 小 |
重點:最貴的那格(大量產出)被移到 Codex 帳單上了,而 Claude 只花在「頭」和「尾」。
一句話總結
Herdr 不會讓 AI 變聰明,它讓你的兩份訂閱可以同時工作。 Claude 想事情、Codex 幹活、Herdr 讓你看得到誰在幹嘛。
🔗 相關筆記
- 07-Agent-Skill讓AI自己操控Herdr — 上一步:必要前置
- 09-實戰-刷題網站Taiwan-IM-board — 下一步:套在刷題網站上
- 10-實戰-Obsidian醫學筆記庫 — 套在這個 vault 上
- 05-Agent偵測與狀態機制 — 為什麼「不要相信狀態」
- Codex 07 - 實戰工作流範例 — 「平行產出 + 中央驗證」的觀念原型
最後更新:2026-08-04
