다른 에이전트 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 설치, 또는 저장소에 복사한 경우
DELEGATE=".claude/skills/delegate-task/delegate.mjs"
# 실행 아티팩트를 드라이버 옆이 아닌 작업 중인 프로젝트에 보관
export DELEGATE_RUNS_DIR="$PWD/.delegate/runs"
플러그인 설치 시 DELEGATE_RUNS_DIR은 필수입니다. 설정하지 않으면 모든 프로젝트의 아티팩트가 공유 플러그인 디렉토리에 누적되며, 여기에는 작업 내용과 CLI 원시 출력이 포함됩니다. 프로젝트의 .gitignore에 .delegate/를 추가하세요. 실행에 관련된 모든 명령(start, status, collect, list, prune)은 동일한 값을 사용해야 합니다.
먼저 사용 가능한 항목 확인
node "$DELEGATE" doctor
doctor는 각 CLI의 버전을 확인하므로 설치되지 않음과 설치되었지만 손상됨을 구분하며, --sandbox가 각 CLI에 실제로 요청하는 사항을 출력합니다.
| CLI | id | 등급 | 재개 | --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 "Add input validation to parse_config() and a test covering the bad-input path."
{"run_id": "codex-…", "state": "running", ...}을 출력하고 반환됩니다. 그 후:
node "$DELEGATE" collect codex-… --wait 300
--wait N은 최대 N초 동안 폴링합니다. --wait 없이 실행 중인 작업에 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는 결정된 것뿐만 아니라 참인 모든 관찰 결과를 나열합니다.dirty_paths_changed— 위임 에이전트가 말한files_claimed와 달리 git이 측정한 변경 사항입니다.files_mismatch는 불일치를 표시합니다.
권한
기본값은 전체 우회(full bypass)입니다. 위임 에이전트는 무인 상태에서 임의의 명령을 실행합니다.
--sandbox는 각 CLI의 실제 읽기 전용 모드(위 표 참조)를 요청하고 경보를 활성화합니다:
read_only_violation은 true / false / null 값입니다. null은 알 수 없음을 의미합니다. git을 사용할 수 없거나 지문(fingerprint) 적용 범위가 불완전한 경우입니다. false로 축소되지 않습니다.
false가 "쓰기(write)가 발생하지 않았음"을 의미하지는 않습니다. 감지된 최종 상태 델타가 없음을 의미합니다. 쓰기 후 되돌리기, gitignored 항목, 저장소 외부의 쓰기는 감지할 수 없습니다.
true가 위임 에이전트가 변경했음을 의미하지는 않습니다 — 동일한 작업 트리에서 동시에 편집한 경우 동일하게 보입니다.
봉투(envelope)는 위임 에이전트에게 커밋하지 말라고 지시하지만, 이는 정책일 뿐 강제 사항이 아닙니다. 강제하는 것은 측정입니다: 실행 기간 동안 HEAD가 이동하면 --allow-commit을 전달하지 않는 한 결과는 검토 필요(head_moved)로 강제됩니다.
실행 계속하기
node "$DELEGATE" start --harness codex --cwd <same dir> --resume <run_id> \
--task "The fix is right, but use the real fixture instead of a mock."
변경된 부분만 보내세요. 재개는 parent_run_id가 설정된 새 run_id를 받으며, CLI, 작업 디렉토리 또는 부모 세션 ID가 일치하지 않으면 거부됩니다.
재개된 디스패치는 부모 세션이 여전히 정책을 준수한다고 가정하지 않고 모든 정책 규칙을 반복합니다.
플래그
| 플래그 | 용도 |
|---|---|
--cwd DIR | 작업 디렉토리 — 항상 명시적으로 설정 |
--model M | 모델 재정의 |
--timeout SEC | 기본값 1800; 사전 검증됨; 만료 시 트리가 종료됨 → abandoned |
--deliverable TEXT | 반환할 결과물 ("unified diff, do not commit") |
--constraint TEXT | 반복 가능한 추가 규칙 |
--sandbox | CLI의 읽기 전용 모드 요청 |
--allow-commit | 커밋 허용, HEAD 이동을 검토 필요로 처리하지 않음 |
--resume <run_id> | 델타 작업으로 완료된 실행의 세션 계속 |
--clean-env / --keep-env N | CLI에 런타임 기본값만 전달; 인증에 필요한 변수당 --keep-env 반복 |
--raw | 작업을 그대로 전송 (상태/요약 손실, --resume과 호환 불가) |
주의사항
- 종료 코드 0이 작업 완료를 의미하지는 않습니다 — 그리고 이 리팩토링 전까지는 0이 아닌 종료 코드가 실패를 의미하지도 않았습니다. 어댑터가 종료 코드를 전달받았지만 아무도 읽지 않아 성공 형태의 이벤트에 종료 코드 1이 붙어
successful로 게시되었습니다. 수정되었으며test/run.mjs의REPAIR-D1케이스에 의해 검증됩니다. 항상status_provenance를 읽고exit_code단독으로 판단하지 마세요. - 토큰 필드는 CLI마다 의미가 다릅니다. Claude의
input_tokens/cache_creation/cache_read는 분리되어 있습니다 — 합산해야 합니다 (프로브 결과 실제로 58,065 토큰을 보낸 요청에 대해input_tokens: 2로 보고됨). Codex의input_tokens는cached_input_tokens를 포함합니다 — 신규 카운트를 얻으려면 빼세요.input_total/input_fresh를 사용하세요;usage_raw는 감사용으로 CLI 자체 숫자를 보관하지만 총계로 표시되지는 않습니다. - 총계는 CLI 간에 비교할 수 없습니다. OpenCode는 단계당 하나의
step_finish를 내보내고 드라이버가 합산하므로 각 단계에서 재전송된 컨텍스트가 매번 계산됩니다. 동일한 단순 작업: 66,341 (codex), 117,014 (claude), 426,523 (opencode). 효율성 순위가 아닙니다. claude에 위임하면 약 58k 토큰의 기본 비용이 발생합니다.claude -p는 작업을 읽기 전에 CLAUDE.md와 발견된 모든 스킬을 로드합니다.- Codex는 MCP 서버를 상속받습니다. Codex가 느리다면
runs/<run_id>/stderr.log를 읽어보세요. 지연은 보통 모델이 아닌 MCP 때문입니다. - Codex는 성공적인 실행에서도
item.type: "error"이벤트를 내보냅니다.turn.failed또는 누락된turn.completed만 카운트됩니다. - 전체 우회는 정말로 샌드박스가 없습니다. OpenCode 위임 에이전트가 한 번
--cwd외부에 파일을 작성한 적이 있습니다.--sandbox를 사용하거나 임시 디렉토리를 사용하세요. - 모든 CLI가 모든 필드를 보고하는 것은 아닙니다. Copilot은 토큰 수를 전혀 내보내지 않습니다 (
fidelity: "unavailable"— 0은 알 수 없음을 의미, 무료가 아님). Codex는 JSONL 어디에도 비용이나 모델을 내보내지 않으므로cost_usd와model은 파싱 실패가 아닌 본질적으로 null입니다.cost_reported/model_reported가 이를 알려주며, 출력 결과에는 "이 CLI에서는 보고되지 않음"이라고 표시됩니다. Claude는 둘 다 보고하고 OpenCode는 비용을 보고합니다. - 작업 텍스트는 셸에 도달하지 않습니다. 각 CLI는 실제 실행 파일로 확인되며
shell:false로 실행됩니다. pi는 자체 저장소에 세션을 유지합니다.--no-session은 의도적으로 전달되지 않습니다. 세션이 없으면 재개할 것이 없습니다. 세션은 작업 디렉토리를 키로~/.pi/agent/sessions/<cwd-slug>/에 저장됩니다.prune은 이들을 건드리지 않습니다. Pi의 인증은 파일 기반(~/.pi/agent/auth.json)이므로--clean-env가 영향을 주지 않습니다.- 슈퍼바이저가 종료된 실행은
lost상태이지, 중단된 것이 아닙니다.collect는 저널과 로그에서 최종 결과를 합성합니다. git 델타는null입니다: 실행 시작 기준이 남아 있지 않으며,false를 보고하면 측정되지 않았다는 보장이 됩니다. - 실행 ID는 유효성이 검사됩니다.
<harness>-<14 digits>-<6 hex>형식과 일치해야 하며 실행 디렉토리 바로 아래에 있어야 합니다. 호출자가 제공한 ID가 상위 디렉토리로 이스케이프할 수 없습니다. - 슈퍼바이저는 죽었지만 CLI가 아직 살아있는 실행은
lost가 아니라adrift입니다.collect는 게시를 거부합니다. 그 시점에 작성된 결과는 아직 진행 중인 실행의 스냅샷이기 때문입니다. 자식 프로세스가 끝날 때까지 기다리거나status가 알려주는 PID를 종료하세요.prune도adrift실행을 삭제하지 않습니다. DELEGATE_BIN_<HARNESS>는 바이너리 위치를 재정의합니다 — 예:DELEGATE_BIN_CODEX=/opt/codex/bin/codex. 또한 테스트 스위트가 토큰을 소모하지 않고 가짜 CLI를 종단 간 구동하는 방법이기도 합니다.
문제 해결
| 증상 | 원인 / 해결책 |
|---|---|
<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 (종료 코드 5) | 분리된 슈퍼바이저가 승인하지 않음; runs/<id>/journal.jsonl 확인. 실행은 containment_evidence: "the harness never launched"와 함께 failed로 종료됨; 저널에 created와 terminal만 있고 슈퍼바이저 PID가 사라졌다면 에이전트가 실행되지 않은 것 |
run <id> still executing (종료 코드 3) | --wait <seconds> 추가 |
Refusing to publish … still running (종료 코드 6) | 실행이 adrift 상태: 슈퍼바이저는 죽었지만 CLI는 살아있음. 기다리거나 PID 종료 |
another process is finalising this run (종료 코드 7) | 다른 라이터가 클레임을 보유 중; 잠시 후 재시도 |
written by a different driver (종료 코드 8) | 결과에 알 수 없는 스키마 포함; 이 빌드는 추측하지 않음 |
상태 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 (기본값 스트림당 32MB)로 제한하고, 제한 초과 후 보존 기간은 DELEGATE_LOG_TAIL_BYTES (기본값 512KB)로 설정합니다.
제한을 초과하면 드라이버는 바이트 접미사 대신 완전한 파싱된 레코드를 유지하므로 텔레메트리가 여전히 파싱됩니다. 윈도우가 보유할 수 없는 레코드는 records_dropped 에 카운트됩니다. 0이 아닌 값은 상태는 여전히 유효하지만 위임 에이전트의 최종 응답이 불완전할 수 있음을 의미합니다.
⚠️ 아티팩트에는 작업 텍스트, 전체 프롬프트 및 CLI의 원시 출력이 포함됩니다 — 민감하게 취급하세요. 최종화는 stdout.log 및 stderr.log에서 토큰 형태와 자격 증명처럼 보이는 NAME=value 쌍을 마스킹합니다 (result.json에서는 마스킹하지 않음). POSIX에서는 실행 디렉토리가 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 픽스처).