--- name: run description: "Run a Claude Code-style dynamic workflow. Plan the task, fan it out across parallel subagents (workflows:worker), independently re-verify every finding (workflows:verifier), attack the result adversarially (workflows:adversary), iterate to convergence, and deliver one coordinated report. Invoke with /workflows:run . Use for large, parallelizable, verifiable work: codebase audits, migrations, broad research, plan stress-testing." user-invocable: true --- # Dynamic Workflows This skill recreates the pattern behind Claude Code's Dynamic Workflows on Mistral Vibe's native components: one orchestrator (you, the main agent) that plans, fans work out to parallel subagents, checks results before folding them in, and iterates until the answers converge. The text after `/workflows:run` is the task. If it is empty, ask for the task before starting. ## When to use a workflow — and when not to USE a workflow when the task is: - **Big and decomposable**: a bug hunt or security audit across a whole service, a migration touching many files, a broad survey. - **Parallelizable**: the subtasks are independent of each other. - **Verifiable**: every result admits an objective check (a test, a compile, a reproduction, a counterexample). DO NOT use one when the task is small, strictly sequential, or cannot be verified. Solve it directly. A workflow costs many times the tokens of a normal turn — every worker, verifier, and adversary is its own conversation. ## Run state and checkpoints All state lives in the scratchpad under `workflows//`: | File | Written in | Contents | |---|---|---| | `plan.md` | Phase 1 | Subtasks with ids, mandates, areas, verification criteria | | `findings.md` | Phase 2 | One block per subtask: worker summaries with evidence | | `verification.md` | Phase 3 | Verdicts: CONFIRMED / REFUTED / UNCERTAIN | | `adversarial.md` | Phase 4 | BREAKER / RISK / NIT objections | | `report.md` | Phase 6 | The final coordinated report | This mirrors the original: "progress is saved as the run goes", so an interrupted run can resume instead of restarting. If `workflows//` already exists, read every file present, tell the user what already ran, and resume from the next incomplete phase. Update the session todo list with the phases as you enter them, so the user sees progress. The plugin also enforces native rails via hooks (`ai.mistral.vibe/hooks.toml`): - `wf-spawn-budget` denies a `workflows:*` spawn once the session has used `WORKFLOWS_SPAWN_CAP` spawns (default 40). If it denies, do not fight it: report the budget as exhausted. Generic subagents are never blocked. - `wf-spawn-audit` appends one line per executed spawn to `${VIBE_HOME:-~/.vibe}/workflows-hooks/spawn-audit.log` — read it in Phase 6 for the run stats instead of counting from memory. ## Phase 0 — Intake 1. Restate the task in one sentence; note repo, key files, constraints. 2. Apply the criteria above. If the task does not qualify, say so and solve it normally. 3. Choose a run id: `wf--`, e.g. `wf-bug-hunt-01`. ## Phase 1 — Plan (with confirmation, like the original) The first time a Claude Code workflow runs, it shows what is about to execute and asks for confirmation. Do the same. 1. Decompose the task into independent subtasks (typically 3-10). 2. Give each subtask a **narrow mandate**: "find X in area Y and summarize what you find" — never "look at everything". 3. Write `plan.md`: for each subtask, an id (`t1`, `t2`, ...), the mandate, the exact area (paths), and how it will be verified. 4. Show the user a compact plan summary: how many workers, what each does, the verification approach, an honest cost warning (each worker is a full conversation). Wait for confirmation before fanning out. ## Phase 2 — Fan-out in waves 1. Spawn one `workflows:worker` per subtask: ``` tools.agents.spawn({ name: "-w", // unique forever in this session config_name: "workflows:worker", message: " Reply with a SUMMARY: finding + evidence (path:line, command, output). Label FACT vs HYPOTHESIS." }) ``` Names are permanent single segments: never reuse one, even across retries. Workers that need a retry get a fresh name (`-w05b`). Give every mandate this shape, so workers never improvise scope: ``` MANDATE (subtask of workflow , repo , branch ): . In particular: . Constraints: <"do not modify any file" | "apply the edit yourself and reply with the diff" | "side effects allowed, report them">. Reply with a SUMMARY: finding + evidence (path:line, command, output). Label FACT vs HYPOTHESIS. ``` 2. If a subtask's mandate produces a file change, the worker applies the edit itself (it has the tools) and replies with the resulting diff — never hand the orchestrator text to transcribe. The orchestrator reviews diffs; transcription loses the file's byte-level conventions (escaping, style) and has caused fix rounds. A worker may run heavy actions (builds, measurements) when the mandate says so; it must then report every file those actions changed as a side effect, beyond the answer to the mandate. 3. Run in **waves of at most 4-6 concurrent workers**. Spawn all workers of a wave in the same turn; do not wait for one before spawning the next. Larger waves drown the session in replies; smaller ones waste wall-clock time. Note the wave's start time in `findings.md`: the cost warning of Phase 1 should be measurable, not felt. 4. Collect results (children cannot be awaited; their replies arrive as messages in your context): a. Replies arrive as runtime notifications: wait for them rather than polling. b. Use `tools.agents.list({})` only when an expected reply is overdue, `tools.self.sleep({ seconds: 30 })` between checks, up to 3 rounds. c. A straggler after 3 rounds: send it a message — "reply now with whatever you have" — via `tools.agents.send_message`, then sleep once more. d. A worker that still answers nothing is dropped, not fatal: mark its subtask `INCOMPLETE` in `findings.md` and move on. 5. Append each reply to `findings.md` as a block: subtask id, worker name, the summary, verbatim. 6. If any wave failed more than half its workers, stop and report to the user instead of burning more budget. ## Phase 3 — Independent verification No finding enters the report unverified. For each significant finding: 1. Spawn a `workflows:verifier` per finding (parallel, waves of 4-6): ``` tools.agents.spawn({ name: "-v", config_name: "workflows:verifier", message: "Finding: . Re-verify it independently from scratch." }) ``` Pass the finding and **how to re-check it** — never the reasoning chain that produced it. Independence is the entire point. 2. Collect verdicts (CONFIRMED / REFUTED / UNCERTAIN) into `verification.md`. 3. REFUTED findings are dropped. UNCERTAIN findings go back into Phase 5. ## Phase 4 — Adversarial pass As in the original: "other agents try to refute what was found." 1. Spawn one `workflows:adversary` on the verified result set (or one per critical finding, max 3): ``` tools.agents.spawn({ name: "-adv1", config_name: "workflows:adversary", message: "Result set: . Break it." }) ``` 2. Collect objections (BREAKER / RISK / NIT) into `adversarial.md`. ## Phase 5 — Convergence loop 1. Fold in what survived: CONFIRMED findings not invalidated by a BREAKER. 2. For every hole — REFUTED results, BREAKER objections, UNCERTAIN verdicts, INCOMPLETE subtasks — launch a targeted wave of workers with narrow mandates that close exactly that hole (back to Phase 2, new worker names). 3. Iterate until results converge, with a hard budget: **max 3 rounds**. Past that, declare what remains uncertain instead of looping forever. This is how a workflow reaches results a single pass cannot — but a loop without a budget just burns tokens. ## Phase 6 — Final report Before writing, run `git status --short` (and the repo's equivalent) and account for every modified file: intended change, side effect of a worker's action (a build can regenerate tracked artifacts nobody mandated), or pre-existing dirt the run discovered. Restore or flag the side effects — the report is also the audit of what the run touched. Write `report.md` and answer the user with one coordinated message: - **Confirmed results** — with evidence (path:line, command, output) - **Rejected or refuted** — and why - **Remaining uncertainties** — after all rounds - **Side effects** — every file the run left on the working tree and its classification; "none" only if you checked - **Run stats** — workers spawned, verifications, adversarial objections, rounds executed, subtasks left INCOMPLETE, total wall-clock (read the spawn audit log instead of counting from memory) ## Golden rules - Narrow mandates: each worker answers ONE question. - "Summarize, don't dump": workers return conclusions with evidence. - Workers apply, the orchestrator reviews: never transcribe a worker's proposed file content by hand — take the diff. - Parallel waves, not sequential queues — with a concurrency cap. - Verify before trusting: nothing unverified in the report. - Account for every working-tree change a run leaves behind. - Budgets are hard: max 3 convergence rounds, then declare uncertainty. - Cost honesty: tell the user a workflow multiplies token usage; for a first run suggest a scoped task.