將任務委派給另一個代理 CLI
在背景中於外部代理 CLI 上執行一個任務,並傳回正規化的結果。
驅動程式:delegate.mjs,位於此技能自己的目錄中(Node ≥ 18,無依賴項)。
行為由 contracts/ 中的三個合約定義——在變更驅動程式之前請先閱讀它們。
start 立即傳回一個 run_id;collect 擷取結果。不會阻塞任何操作。
首先解析驅動程式和執行目錄
安裝此技能的位置決定了 delegate.mjs 的所在位置,而執行工件預設會儲存在驅動程式的旁邊。請在每個工作階段中設定兩者一次,然後在後續每個命令中使用 $DELEGATE:
# Claude Code 外掛安裝 (agent-tools@sanduq)
DELEGATE="$CLAUDE_PLUGIN_ROOT/skills/delegate-task/delegate.mjs"
# npx skills install,或提交到儲存庫的副本
DELEGATE=".claude/skills/delegate-task/delegate.mjs"
# 將執行工件保留在正在處理的專案中,而非驅動程式旁
export DELEGATE_RUNS_DIR="$PWD/.delegate/runs"
對於外掛安裝,DELEGATE_RUNS_DIR 是必要的:如果沒有設定,來自每個專案的工件會累積在共用的外掛目錄中,而這些工件包含你的任務文字和 harness 的原始輸出。請將 .delegate/ 新增到專案的 .gitignore 中。每個觸及執行的命令——start、status、collect、list、prune——都必須看到相同的值。
首先檢查可用的項目
node "$DELEGATE" doctor
doctor 會探查每個 CLI 的版本,因此它可以區分未安裝和已安裝但損壞的情況——並列印出 --sandbox 實際向每個 CLI 請求的內容。
| harness | id | tier | resume | --sandbox 請求的內容 |
|---|---|---|---|---|
| Claude Code | claude | verified | verified | --permission-mode plan |
| OpenAI Codex | codex | verified | verified | -s read-only (CLI 強制執行) |
| OpenCode | opencode | verified | verified | --agent plan |
| GitHub Copilot | copilot | experimental | experimental | --mode plan |
| Pi | pi | experimental | experimental | --no-approve --tools read,grep,find,ls |
優先使用 claude、codex 或 opencode。
執行委派
node "$DELEGATE" start \
--harness codex \
--cwd /path/to/workspace \
--timeout 600 \
--task "為 parse_config() 新增輸入驗證,以及一個涵蓋錯誤輸入路徑的測試。"
輸出 {"run_id": "codex-…", "state": "running", ...} 並回傳。然後:
node "$DELEGATE" collect codex-… --wait 300
--wait N 會最多輪詢 N 秒。如果沒有此選項,則若執行仍在進行中,collect 會以狀態碼 3 退出。
其他命令:
node "$DELEGATE" status <run_id> # starting|running|stalled|adrift|lost|done
node "$DELEGATE" collect <run_id> --json # 機器可讀的結果 — 解析此內容
node "$DELEGATE" list # 所有執行,最早的排在最前面
node "$DELEGATE" prune --keep 20 --yes # 刪除舊的執行工件
node "$DELEGATE" contract # 機器可讀的旗標、欄位、退出碼
讀取結果
Status SUCCESSFUL
Because harness_telemetry
Changes
measured greeting.txt
claimed greeting.txt
Permission requested=bypass applied=codex: --dangerously-bypass-approvals-and-sandbox
三個欄位承載了大部分意義:
status—successful/failed/abandoned。status_provenance.primary— 為何是該狀態,用一個詞表示:timeout、spawn_error、signal、exit_code、parse_error、telemetry_incomplete、harness_telemetry、self_report、head_moved、index_moved、relay_aborted、supervisor_lost、legacy。 絕不要在不了解是哪個原因產生此狀態的情況下報告狀態。evidence會列出每一個 為 true 的觀察結果,而不僅僅是勝出的那個。dirty_paths_changed— git 測量到的內容,與files_claimed(委派者聲稱的內容)相對。files_mismatch會標記不一致之處。
權限
**預設為完全繞過。**委派者會在無人值守的情況下執行任意命令。
--sandbox 會請求每個 CLI 真正的唯讀模式(上表),並開啟絆網:
read_only_violation 為 true / false / null。null 表示未知——Git
不可用或指紋覆蓋不完整。它永遠不會被摺疊為 false。
false 並不表示「未發生寫入」。 它表示未檢測到被覆蓋的最終狀態差異。
它無法看到寫入後還原、任何被 gitignore 忽略的內容,或儲存庫外部的任何寫入。
true 並不表示是委派者所為 — 同一個工作樹中的並行編輯看起來完全相同。
信封告訴委派者不要提交,但這是政策,而非強制執行。真正執行強制的是測量:
如果在執行期間 HEAD 移動,則結果會被強制標記為需要審查(head_moved),除非你傳遞了
--allow-commit。
繼續執行
node "$DELEGATE" start --harness codex --cwd <相同目錄> --resume <run_id> \
--task "修正是對的,但請使用真實的 fixture 而不是 mock。"
僅傳送差異部分。繼續執行會獲得一個新的 run_id,並設有 parent_run_id,且如果
harness、工作目錄或父項的 session id 不一致,則會拒絕執行。
繼續的任務分發會重複執行每個政策規則,而不是假設父項工作階段仍然遵守它們。
旗標
| 旗標 | 用途 |
|---|---|
--cwd DIR | 工作目錄 — 始終明確設定它 |
--model M | 覆蓋模型 |
--timeout SEC | 預設 1800;會預先驗證;到期時進程樹將被終止 → abandoned |
--deliverable TEXT | 要回傳的內容(「一個統一差異,請勿提交」) |
--constraint TEXT | 可重複的額外規則 |
--sandbox | 請求 harness 的唯讀模式 |
--allow-commit | 允許提交,並停止將 HEAD 移動視為需要審查 |
--resume <run_id> | 使用差異任務繼續已完成的執行工作階段 |
--clean-env / --keep-env N | 僅向 CLI 提供執行時基礎環境;為每個驗證所需的變量重複 --keep-env |
--raw | 逐字傳送任務(會失去狀態/摘要;與 --resume 不相容) |
注意事項
- 退出碼 0 並不表示任務已完成——而在本次重構之前,非零退出碼也不表示失敗。適配器會收到退出碼,但沒有一個會讀取它,因此一個類成功事件加上退出碼 1 會被發布為
successful。已修復;由test/run.mjs中的REPAIR-D1案例固定。始終讀取status_provenance,絕不單獨讀取exit_code。 - Token 欄位在不同 harness 之間意義不同。 Claude 的
input_tokens/cache_creation/cache_read是不相交的——將它們相加(一次探查報告對於一個實際發送了 58,065 的請求,input_tokens為 2)。Codex 的input_tokens包含cached_input_tokens——減去以獲得新的計數。使用input_total/input_fresh;usage_raw保留 harness 自己的數字以供審計,但絕不會顯示為總計。 - 總計在不同 harness 之間無法比較。 OpenCode 每個步驟發出一個
step_finish,而驅動程式會將其加總,因此每次步驟重新傳送的上下文都會被計算在內。相同簡單任務: 66,341(codex)、117,014(claude)、426,523(opencode)。不是效率排名。 - 委派給
claude有大約 58k 的 token 基礎開銷。claude -p會在讀取任務之前載入 CLAUDE.md 和每個發現的技能。 - Codex 會繼承你的 MCP 伺服器。 如果 codex 感覺很慢,請讀取
runs/<run_id>/stderr.log—— 延遲通常來自 MCP,而不是模型。 - Codex 會在成功執行時發出
item.type: "error"事件。 只有turn.failed或缺少turn.completed才算數。 - 完全繞過確實是無沙箱的。 一個 OpenCode 委派者曾經在它的
--cwd之外寫入了一個檔案。請使用--sandbox,或使用一次性的目錄。 - 並非每個 harness 都會報告每個欄位。 Copilot 完全不發出 Token 計數
(
fidelity: "unavailable"——零表示未知,而非免費)。Codex 在其 JSONL 中任何地方都不會發出成本或模型,因此cost_usd和model本質上為 null,而不是解析失敗——cost_reported/model_reported會說明哪個被報告了,而列印的結果會顯示「此 harness 未報告」。Claude 會報告兩者;OpenCode 會報告成本。 - 任務文字永遠不會到達 shell。 每個 CLI 都會被解析為一個真實的可執行檔,並以
shell:false生成。 pi會在其自己的儲存中保留一個工作階段。--no-session被特意地不傳遞——沒有工作階段就沒有什麼可以繼續。工作階段會存放在~/.pi/agent/sessions/<cwd-slug>/中,以工作目錄為鍵;prune不會觸及它們。Pi 的驗證基於檔案(~/.pi/agent/auth.json),因此--clean-env不會破壞它。- 其管理進程被殺死的執行是
lost,而不是卡住。collect會從日誌和檔案中合成一個終端結果。其 git 差異為null:沒有執行開始的基準線保留下來,而報告false將是一種沒有測量到任何東西的保證。 - Run id 會經過驗證。 它們必須符合
<harness>-<14 位數字>-<6 個十六進位字元>,且必須直接解析到 runs 目錄下。呼叫者提供的 id 不能遍歷出去。 - 管理進程已死亡但其 harness 仍然存活的執行是
adrift,而不是lost。collect拒絕發布,因為在該時間點寫入的結果會快照到一個仍在進行中的執行。請等待子進程完成,或殺死status命名的 pid。prune也不會刪除漂流的執行。 DELEGATE_BIN_<HARNESS>會覆蓋執行檔的查找位置——例如,DELEGATE_BIN_CODEX=/opt/codex/bin/codex。測試套件也透過此方式來端到端驅動偽造的 harness,而無需花費任何 token。
故障排除
| 症狀 | 原因 / 修復 |
|---|---|
<bin> not found on PATH | 該 CLI 未安裝;執行 doctor |
found <path> but could not resolve what it launches | CLI 安裝在非 npm 的 .cmd shim 後面,此驅動程式無法解碼 |
doctor 顯示 BROKEN: probe timed out | 通常是冷啟動;在得出任何結論之前重新執行 doctor |
supervisor failed to start (exit 5) | 分離的管理進程從未確認;檢查 runs/<id>/journal.jsonl。該執行已最終確定為 failed,並帶有 containment_evidence: "the harness never launched";如果日誌僅包含 created 和 terminal 且管理進程 pid 已消失,則表示沒有代理程式執行過 |
run <id> still executing (exit 3) | 新增 --wait <seconds> |
Refusing to publish … still running (exit 6) | 執行處於 adrift 狀態:管理進程已死亡,但 harness 仍在執行。等待,或殺死它命名的 pid |
another process is finalising this run (exit 7) | 一個存活的寫入者持有鎖;稍後重試 |
written by a different driver (exit 8) | 結果包含未知的 schema;此版本不會嘗試猜測 |
狀態 abandoned,來源 supervisor_lost | 管理進程被殺死;在重新分發前檢查工作樹 |
狀態 failed,來源 head_moved / index_moved | 在執行期間發生了提交或暫存;樹已保留,請審查它 |
摘要顯示 (no summary produced) | 委派者從未發出結果區塊;讀取 runs/<run_id>/stdout.log |
檔案
執行工件位於 $DELEGATE_RUNS_DIR/<run_id>/ 中(prompt.txt、meta.json、journal.jsonl、
stdout.log、stderr.log、result.json)。如果未設定,DELEGATE_RUNS_DIR 預設為驅動程式旁的
runs/——這在外掛安裝時是共用的外掛目錄,因此請設定它。使用 DELEGATE_MAX_LOG_BYTES(預設每個串流 32 MB)來限制日誌大小,並使用
DELEGATE_LOG_TAIL_BYTES(預設 512 KB)來設定超出限制後的保留視窗。
超出限制後,驅動程式會保留完整的已解析記錄,而不是位元組後綴,因此遙測資料仍然可以解析。視窗無法容納的記錄會計入
records_dropped——非零值表示狀態仍然正確,但委派者自己的最終答案可能不完整。
⚠️ 工件包含你的任務文字、完整的提示詞以及 harness 的原始輸出——請將其視為敏感資訊。 最終化處理會遮罩 stdout.log 和 stderr.log 中的 token 形狀和看起來像憑證的 NAME=value 配對(不會在 result.json 中遮罩)。在 POSIX 系統上,runs 目錄會設定為 chmod 0700;
在 Windows 上,權限是繼承的,此驅動程式無法限制它們。成功的 collect 會刪除早於
DELEGATE_PRUNE_DAYS 天(預設 30;0 表示停用)的已完成執行;使用 prune 可以更早清理。
深入了解
-
有關已知的本地 CLI 檢查批次,請閱讀原生檢查執行器合約。 它涵蓋了 JSON argv 計劃、不可變的嘗試、有邊界的收集以及 PowerShell 調用。 使用相同的參考資料來處理
collect --summary、僅有心跳的診斷和選擇性的啟動截止時間。 -
contracts/status-precedence.md— 如何決定狀態,以及要測試的交叉點 -
contracts/git-fields.md— 絆網測量什麼以及它無法看到什麼 -
contracts/result-schema-v2.md— 結果形狀、v1 向後讀取、日誌、單一寫入者 -
references/writing-the-brief.md— 如何撰寫委派者可以盲目執行的任務 -
references/reviewing-the-result.md— 如何審查回傳的內容,包括掃描 -
references/task-queues.md— 在不失去線索的情況下執行幾個相依任務
測試:從此技能目錄執行 node test/run.mjs。
執行回歸測試:node --test test/execution.test.mjs(Node/Python CLI fixture)。