Runs large fan-out work as a workflow: the plan, the loop and every intermediate
result live in a script and on disk, so the parent's context holds only verified
results. Covers one-shot fan-outs, adversarial convergence (attempts + refuters),
and multi-wave campaigns that integrate dozens of worker branches. It does not
make delegate_task durable across restarts; that is the kanban swarm's job.
Reach for it when the unit of work is clear (a file, an endpoint, a record) and
there are more units than one context can hold. Skip it for under ~10 units or
for serial chains. For a refactor or fix campaign on hermes-agent itself, load
hermes-agent (the dev workflow) alongside; this skill owns the fan-out shape.
delegate_task available and delegation.max_concurrent_children sized for
the wave (default 10; the runtime rejects a tasks=[] larger than that with a
clear error rather than queueing). delegation.max_spawn_depth >= 2 only if
children must fan out themselves.$TMPDIR, else the platform temp dir). Never a literal /tmp:
Termux has no such directory and native Windows breaks on it. Use <tmp>/wf_<name>_<uuid>/, unique per
run, so an interrupted earlier run cannot leave stale outputs to be misread.execute_code for the deterministic layer (only web_search, web_extract,
read_file, write_file, search_files, terminal, patch exist inside it).Two layers, split by a real capability boundary:
Layer A - execute_code script | Layer B - delegate_task batch | |
|---|---|---|
| Use for | DETERMINISTIC work: fetch N URLs, parse N files, run N commands, template N outputs, build manifests, merge outputs | LLM-JUDGMENT work: classify, review, decide, write, refute, refactor one unit |
| Holds | loop, branching, intermediate variables | nothing; one call with tasks=[...], each task its own isolated agent |
| Tools | the sandbox set above; it can NOT call delegate_task | the parent's toolsets, inherited unchanged (no per-task narrowing); children lose delegate_task, clarify, memory, send_message, cronjob_manage |
| Concurrency | yours (ThreadPoolExecutor, batches) | bounded by delegation.max_concurrent_children |
| Cost | tool calls only | one full agent tree per task; multiplies linearly |
Do the deterministic part in Layer A first, fan out only the irreducibly-LLM step in Layer B, synthesize on the parent.
A top-level delegate_task returns immediately with one handle per task; each
child's result re-enters the conversation as a new message when it finishes. You
cannot read out_*.csv on the line after the call. Finish whatever does not
depend on the children, give a one-line status, and END YOUR TURN; act on each
result message as it lands. An ordinary follow-up user message does not cancel
children; /stop, /new and process exit do. Only a delegation issued by an
orchestrator subagent (depth > 0) is synchronous.
<run>/manifest.jsonl; print count + run dir.summary field (it truncates under load); delimiter-separated lines over JSON.max_concurrent_children, issue bounded waves yourself.delegate_task(tasks=[...]); each task reads its slice, writes
<run>/out_<i>.csv, prints a status word, stops.context, each writing one claim per line to
<run>/attempt_<i>.md. Located, individually falsifiable claims only
("POST /api/users/:id/role in src/routes/users.ts:142 has no role check");
a refuter cannot break "the auth layer has problems".claim_idx|survives|counter_evidence. Give them the sources, not the
attempts' reasoning.The same mechanic protects the parent from its own wrong premises: when you hand children a heuristic ("every patch target on a facade is a dead seam"), tell them to refute it with evidence before acting on it. Four squads doing so turned a 647-site blanket rewrite into 59 real fixes and saved 130+ green tests.
The one-shot recipe does not scale to a whole-codebase pass. What did:
BRIEF.md plus a per-cluster task_<cluster>.md. Every child reads
both. When the fleet drifts (children shaving docstrings instead of cutting
code), patch the brief once and steer; re-dispatched children inherit the fix.git commit -- <paths> only; a bare commit swept a sibling's staged hunks.completed with a few dozen log lines, or
with 0 commits on its branch, has not finished; look for its sub-branches or
re-dispatch it with the predecessor's worktree and diff.git rev-list --count <integration>..<branch>
is 0 for EVERY branch. Workers keep committing after you merge their tip;
168 commits across six slices were once left behind that way.-j.
Many parallel low--j runners were slower AND killed each other's process
groups. Red files are re-run on a bare origin/main worktree in the same
venv; identical per-file failure sets are pre-existing, not yours.HERMES_HOME,
expectation written before the check, evidence on disk, report only, and a
PR-vs-main difference is the only thing that counts as a regression. Green
unit tests missed the one P0 (a logged-in code path no test exercised).HANDOFF.md: why it died, which handles are dead,
per-branch scorecard (LOC delta, import smoke, targeted tests), and the exact
re-dispatch text. Snapshot every dirty worktree into a wip: commit first.delegate_task inside an execute_code script: not in the sandbox.delegate_task: it is turn-scoped
and dies with the process. Durable graph = kanban swarm; one-off = cronjob.summary for content, or status=completed for completion.git stash anywhere in a worktree campaign: refs/stash is shared across
worktrees and another worker will pop your edits. Compare via a temp worktree.out_*.csv exists and was written this run.68fa7e9
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.