Delegiere eine Aufgabe an eine andere Agenten-CLI
Führt eine Aufgabe auf einer externen Agenten-CLI im Hintergrund aus und gibt ein normiertes Ergebnis zurück.
Treiber: delegate.mjs, im eigenen Verzeichnis dieser Skill (Node ≥ 18, keine Abhängigkeiten).
Das Verhalten wird durch drei Verträge in contracts/ definiert — lies sie, bevor du den Treiber änderst.
start gibt sofort eine run_id zurück; collect ruft das Ergebnis ab. Nichts blockiert dich.
Zuerst den Treiber und das Ausführungsverzeichnis auflösen
Wo diese Skill installiert ist, bestimmt, wo delegate.mjs liegt, und Ausführungsartefakte werden standardmäßig
neben dem Treiber abgelegt. Setze beide einmal pro Sitzung und verwende dann $DELEGATE in jedem
Befehl unten:
# Claude Code Plugin-Installation (agent-tools@sanduq)
DELEGATE="$CLAUDE_PLUGIN_ROOT/skills/delegate-task/delegate.mjs"
# npx skills install, oder eine Kopie, die in das Repository eingepflegt wurde
DELEGATE=".claude/skills/delegate-task/delegate.mjs"
# Halte Ausführungsartefakte im bearbeiteten Projekt, nicht neben dem Treiber
export DELEGATE_RUNS_DIR="$PWD/.delegate/runs"
DELEGATE_RUNS_DIR ist erforderlich für eine Plugin-Installation: Ohne sie sammeln sich Artefakte aus jedem Projekt
im gemeinsamen Plugin-Verzeichnis, und sie enthalten deinen Aufgabentext und die Rohausgabe des Harnesses.
Füge .delegate/ zur .gitignore des Projekts hinzu. Jeder Befehl, der einen Lauf berührt
— start, status, collect, list, prune — muss denselben Wert sehen.
Zuerst prüfen, was verfügbar ist
node "$DELEGATE" doctor
doctor überprüft die Version jeder CLI und unterscheidet so nicht installiert von installiert aber
kaputt — und gibt aus, was --sandbox tatsächlich von jeder verlangt.
| Harness | id | Stufe | Fortsetzen | --sandbox-Anfragen |
|---|---|---|---|---|
| Claude Code | claude | verifiziert | verifiziert | --permission-mode plan |
| OpenAI Codex | codex | verifiziert | verifiziert | -s read-only (CLI-erzwungen) |
| OpenCode | opencode | verifiziert | verifiziert | --agent plan |
| GitHub Copilot | copilot | experimentell | experimentell | --mode plan |
| Pi | pi | experimentell | experimentell | --no-approve --tools read,grep,find,ls |
Bevorzuge claude, codex oder opencode.
Eine Delegation ausführen
node "$DELEGATE" start \
--harness codex \
--cwd /pfad/zum/workspace \
--timeout 600 \
--task "Füge Eingabevalidierung zu parse_config() und einen Test für den Pfad mit fehlerhaften Eingaben hinzu."
Gibt {"run_id": "codex-…", "state": "running", ...} aus und kehrt zurück. Dann:
node "$DELEGATE" collect codex-… --wait 300
--wait N pollt bis zu N Sekunden. Ohne dies beendet sich collect mit Exit-Code 3, wenn der Lauf noch läuft.
Andere Befehle:
node "$DELEGATE" status <run_id> # starting|running|stalled|adrift|lost|done
node "$DELEGATE" collect <run_id> --json # das maschinenlesbare Ergebnis — dies parsen
node "$DELEGATE" list # alle Läufe, älteste zuerst
node "$DELEGATE" prune --keep 20 --yes # alte Laufartefakte löschen
node "$DELEGATE" contract # maschinenlesbare Flags, Felder, Exit-Codes
Das Ergebnis lesen
Status SUCCESSFUL
Weil harness_telemetry
Änderungen
gemessen greeting.txt
beansprucht greeting.txt
Berechtigung angefordert=bypass angewendet=codex: --dangerously-bypass-approvals-and-sandbox
Drei Felder tragen die meiste Bedeutung:
status—successful/failed/abandoned.status_provenance.primary— warum dieser Status, in einem Wort:timeout,spawn_error,signal,exit_code,parse_error,telemetry_incomplete,harness_telemetry,self_report,head_moved,index_moved,relay_aborted,supervisor_lost,legacy. Melde niemals einen Status, ohne zu wissen, welcher dieser Werte ihn erzeugt hat.evidencelistet jede Beobachtung auf, die wahr war, nicht nur die, die gewonnen hat.dirty_paths_changed— was git gemessen hat, im Gegensatz zufiles_claimed, was der Delegierte gesagt hat.files_mismatchzeigt Unstimmigkeiten an.
Berechtigungen
Standardmäßig vollständige Umgehung. Der Delegierte führt beliebige Befehle unbeaufsichtigt aus.
--sandbox fordert den echten Schreibschutzmodus jeder CLI an (Tabelle oben) und schaltet den Tripwire ein:
read_only_violation ist true / false / null. null bedeutet unbekannt — git war
nicht verfügbar oder die Fingerabdruckabdeckung war unvollständig. Es wird niemals auf false reduziert.
false bedeutet nicht "keine Schreibvorgänge sind aufgetreten". Es bedeutet, dass keine abgedeckte
Änderung des Endzustands erkannt wurde. Es kann ein Schreiben-und-Zurücksetzen, alles was gitignoriert wird, oder
jegliche Schreibvorgänge außerhalb des Repos nicht sehen. true bedeutet nicht, dass der Delegierte es getan hat
— eine gleichzeitige Bearbeitung im selben Arbeitsverzeichnis sieht identisch aus.
Der Umschlag weist den Delegierten an, nicht zu committen, aber das ist Richtlinie, keine Durchsetzung.
Was es durchsetzt, ist die Messung: Wenn HEAD sich während des Lauffenssters bewegt, wird das Ergebnis zu
„Überprüfung erforderlich“ gezwungen (head_moved), es sei denn, du hast --allow-commit übergeben.
Einen Lauf fortsetzen
node "$DELEGATE" start --harness codex --cwd <gleiches verzeichnis> --resume <run_id> \
--task "Der Fix ist richtig, aber verwende die echte Testvorrichtung anstelle eines Mocks."
Sende nur das Delta. Resume erhält eine neue run_id mit gesetztem parent_run_id und lehnt ab, wenn
sich der Harness, das Arbeitsverzeichnis oder die Sitzungs-ID des übergeordneten Laufs nicht decken.
Ein fortgesetzter Dispatch wiederholt jede Richtlinienregel, anstatt anzunehmen, dass die übergeordnete Sitzung sie noch einhält.
Flags
| Flag | Verwendung |
|---|---|
--cwd DIR | Arbeitsverzeichnis — immer explizit setzen |
--model M | Modell überschreiben |
--timeout SEK | Standard 1800; vorab validiert; bei Ablauf wird der Baum gekillt → abandoned |
--deliverable TEXT | Was zurückgegeben werden soll („ein Unified-Diff, nicht committen“) |
--constraint TEXT | Wiederholbare zusätzliche Regel |
--sandbox | Schreibschutzmodus des Harnesses anfordern |
--allow-commit | Committen erlauben und eine verschobene HEAD nicht mehr als überprüfungsbedürftig behandeln |
--resume <run_id> | Einen abgeschlossenen Lauf mit einer Delta-Aufgabe fortsetzen |
--clean-env / --keep-env N | Der CLI nur Laufzeit-Basics übergeben; --keep-env pro benötigter Variable für Authentifizierung wiederholen |
--raw | Aufgabe wörtlich senden (verliert Status/Zusammenfassung; inkompatibel mit --resume) |
Fallstricke
- Exit-Code 0 bedeutet nicht, dass die Aufgabe erledigt war — und bis zu dieser Umgestaltung bedeutete ein von Null
verschiedener Exit nicht, dass sie fehlgeschlagen ist. Adapter erhielten den Exit-Code und keiner las ihn, also
wurde ein erfolgsförmiges Ereignis plus Exit 1 als
successfulveröffentlicht. Behoben; verankert durchtest/run.mjs-FallREPAIR-D1. Lies immerstatus_provenance, niemalsexit_codeallein. - Token-Felder bedeuten pro Harness unterschiedliche Dinge. Claudes
input_tokens/cache_creation/cache_readsind disjunkt — summiere sie (ein Testbericht meldeteinput_tokens: 2für eine Anfrage, die wirklich 58.065 sendete). Codexsinput_tokensist inklusiv voncached_input_tokens— subtrahiere für die frischen Zählung. Verwendeinput_total/input_fresh;usage_rawbehält die eigenen Zahlen des Harnesses für die Prüfung, wird aber niemals als Gesamtsumme angezeigt. - Summen sind nicht über Harnesses hinweg vergleichbar. OpenCode gibt ein
step_finishpro Schritt aus und der Treiber summiert sie, sodass der Kontext, der bei jedem Schritt erneut gesendet wird, jedes Mal gezählt wird. Gleiche triviale Aufgabe: 66.341 (codex), 117.014 (claude), 426.523 (opencode). Keine Effizienzrangliste. - Die Delegierung an
claudehat eine Untergrenze von ~58k Token.claude -plädt CLAUDE.md und jede entdeckte Skill, bevor die Aufgabe gelesen wird. - Codex erbt deine MCP-Server. Wenn Codex sich langsam anfühlt, lies
runs/<run_id>/stderr.log— die Verzögerung liegt normalerweise an MCP, nicht am Modell. - Codex gibt bei erfolgreichen Läufen
item.type: "error"-Ereignisse aus. Nurturn.failedoder ein fehlendesturn.completedzählt. - Vollständige Umgehung ist wirklich unsandboxed. Ein OpenCode-Delegierter schrieb einmal eine Datei außerhalb
seines
--cwd. Verwende--sandboxoder ein Wegwerfverzeichnis. - Nicht jeder Harness meldet jedes Feld. Copilot gibt überhaupt keine Tokenzahlen aus
(
fidelity: "unavailable"— Nullwerte bedeuten unbekannt, nicht kostenlos). Codex gibt weder Kosten noch ein Modell irgendwo in seinem JSONL aus, also sindcost_usdundmodelvon Natur aus null, nicht aufgrund eines Parsingfehlers —cost_reported/model_reportedsagen, welche, und das gedruckte Ergebnis lautet „von diesem Harness nicht gemeldet“. Claude meldet beides; OpenCode meldet Kosten. - Aufgabentext erreicht niemals eine Shell. Jede CLI wird zu einer echten ausführbaren Datei aufgelöst und
mit
shell:falsegestartet. pibehält eine Sitzung in seinem eigenen Speicher.--no-sessionwird bewusst nicht übergeben — ohne Sitzung gibt es nichts, was fortgesetzt werden könnte. Sitzungen landen in~/.pi/agent/sessions/<cwd-slug>/, abhängig vom Arbeitsverzeichnis;pruneberührt sie nicht. Pis Authentifizierung ist dateibasiert (~/.pi/agent/auth.json), also bricht--clean-envsie nicht.- Ein Lauf, dessen Supervisor getötet wird, ist
lost, nicht festgefahren.collectsynthetisiert ein terminales Ergebnis aus dem Journal und den Logs. Sein Git-Delta istnull: keine Basislinie zum Start des Laufs hat überlebt, und das Melden vonfalsewäre eine Zusicherung, dass nichts gemessen wurde. - Lauf-IDs werden validiert. Sie müssen
<harness>-<14 ziffern>-<6 hex>entsprechen und müssen direkt unter dem Ausführungsverzeichnis aufgelöst werden. Eine vom Aufrufer bereitgestellte ID kann nicht aus diesem Verzeichnis ausbrechen. - Ein toter Supervisor, dessen Harness noch lebt, ist
adrift, nichtlost.collectweigert sich zu veröffentlichen, weil ein dann geschriebenes Ergebnis einen noch laufenden Lauf einfrieren würde. Warte auf das Kind oder töte die PID, diestatusnennt.prunewird einen adrift-Lauf ebenfalls nicht löschen. DELEGATE_BIN_<HARNESS>überschreibt, wo eine Binärdatei gefunden wird — z.B.DELEGATE_BIN_CODEX=/opt/codex/bin/codex. So treibt die Testsammlung auch einen Fake-Harness Ende-zu-Ende, ohne einen Token auszugeben.
Fehlerbehebung
| Symptom | Ursache / Behebung |
|---|---|
<bin> nicht auf PATH gefunden | diese CLI ist nicht installiert; führe doctor aus |
<pfad> gefunden, aber konnte nicht auflösen, was gestartet wird | die CLI ist hinter einem nicht-npm-.cmd-Shim installiert, den dieser Treiber nicht dekodieren kann |
doctor zeigt BROKEN: probe timed out | normalerweise ein Kaltstart; führe doctor erneut aus, bevor du Schlussfolgerungen ziehst |
Supervisor konnte nicht gestartet werden (Exit 5) | der getrennte Supervisor hat nie bestätigt; überprüfe runs/<id>/journal.jsonl. Der Lauf wird mit failed abgeschlossen mit containment_evidence: "the harness never launched"; wenn das Journal nur created und terminal enthält und die Supervisor-PID weg ist, lief kein Agent |
Lauf <id> wird noch ausgeführt (Exit 3) | füge --wait <sekunden> hinzu |
Verweigere Veröffentlichung … läuft noch (Exit 6) | der Lauf ist adrift: der Supervisor starb, aber der Harness lebt. Warte oder töte die PID, die er nennt |
Ein anderer Prozess schließt diesen Lauf ab (Exit 7) | ein lebender Schreiber hält den Anspruch; versuche es gleich noch einmal |
von einem anderen Treiber geschrieben (Exit 8) | das Ergebnis trägt ein unbekanntes Schema; dieser Build wird nicht darüber raten |
Status abandoned, Herkunft supervisor_lost | der Supervisor wurde getötet; überprüfe den Arbeitsbaum, bevor du erneut auslöst |
Status failed, Herkunft head_moved / index_moved | etwas hat während des Laufs committet oder gestaged; der Baum ist erhalten, überprüfe ihn |
Zusammenfassung lautet (keine Zusammenfassung erstellt) | der Delegierte hat den Ergebnisblock nie ausgegeben; lies runs/<run_id>/stdout.log |
Dateien
Laufartefakte liegen in $DELEGATE_RUNS_DIR/<run_id>/ (prompt.txt, meta.json, journal.jsonl,
stdout.log, stderr.log, result.json). Wenn nicht gesetzt, standardmäßig DELEGATE_RUNS_DIR zu runs/ neben
dem Treiber — was bei einer Plugin-Installation das gemeinsame Plugin-Verzeichnis ist, also setze es. Begrenze die Log-Größe
mit DELEGATE_MAX_LOG_BYTES (Standard 32 MB pro Stream) und das Aufbewahrungsfenster nach der Kappung mit
DELEGATE_LOG_TAIL_BYTES (Standard 512 KB).
Nach der Kappung behält der Treiber vollständige geparste Datensätze statt eines Byte-Suffixes,
also parst die Telemetrie immer noch. Datensätze, die das Fenster nicht halten kann, werden in records_dropped gezählt
— ein Wert ungleich Null bedeutet, dass der Status immer noch gültig ist, aber die eigene endgültige Antwort des Delegierten
möglicherweise unvollständig ist.
⚠️ Artefakte enthalten deinen Aufgabentext, den vollständigen Prompt und die Rohausgabe des Harnesses — behandle sie als
vertraulich. Die Finalisierung maskiert Token-Formen und anmeldeinformationsartige NAME=value-Paare in
stdout.log und stderr.log (nicht in result.json). Auf POSIX wird das Ausführungsverzeichnis auf chmod 0700 gesetzt;
auf Windows werden Berechtigungen vererbt und dieser Treiber kann sie nicht einschränken. Ein erfolgreicher collect
löscht abgeschlossene Läufe, die älter als DELEGATE_PRUNE_DAYS Tage sind (Standard 30; 0 deaktiviert); räume
früher mit prune auf.
Tiefergehende Informationen
-
Für eine Reihe bekannter lokaler CLI-Prüfungen lies den nativen Check-Runner-Vertrag. Er deckt JSON-argv-Pläne, unveränderliche Versuche, begrenzte Sammlung und PowerShell-Aufrufe ab. Verwende dieselbe Referenz für
collect --summary, Heartbeat-only-Diagnosen und optionale Startfristen. -
contracts/status-precedence.md— wie ein Status entschieden wird, und das Kreuzprodukt zum Testen -
contracts/git-fields.md— was der Tripwire misst und was er nicht sehen kann -
contracts/result-schema-v2.md— die Ergebnisform, v1-Rückwärtslesung, Journal, Single-Writer -
references/writing-the-brief.md— wie man eine Aufgabe schreibt, die der Delegierte blind ausführen kann -
references/reviewing-the-result.md— wie man das, was zurückkommt, überprüft, einschließlich der Bereinigung -
references/task-queues.md— mehrere abhängige Aufgaben ausführen, ohne den Faden zu verlieren
Tests: node test/run.mjs, aus dem Verzeichnis dieser Skill.
Ausführungsregressionen: node --test test/execution.test.mjs (Node/Python-CLI-Fixtures).