本文へスキップ
MCP ThesaurusMCP Thesaurus

Swarm Brainstorm

コミュニティGood67/100申請する

updated 1mo ago

A single brainstorm prompt returns the confident middle of the model's output distribution. This skill is a rig for testing a specific, unvalidated bet: that fanning out many cheap, radically-constrained persona agents in parallel populates the tails of that distribution, and that a lexical statistics step can cheaply separate genuine outlier signal from both dense consensus and incoherent noise — without needing embeddings.

ソースウェブサイトドキュメント

Swarm Brainstorm で何ができる?


name: swarm-brainstorm description: 'Fan out a swarm of cheap, persona-driven agents to brainstorm a problem, statistically filter the raw output for genuine outliers against the consensus baseline, and synthesize survivors into a baseline-vs-emergent report. Use when the user wants divergent or contrarian ideation that goes beyond a single prompt''s safe middle-of-the-distribution answers, references "swarm brainstorm" or the "Court Jester Protocol", or asks to generate a large batch of wild/adversarial ideas and extract the ones that are actually novel rather than noise.' argument-hint: "[problem statement] [size: s|m|l|xl or a number]"

Swarm Brainstorm (Court Jester Protocol)

Premise and what this skill is

A single brainstorm prompt returns the confident middle of the model's output distribution. This skill is a rig for testing a specific, unvalidated bet: that fanning out many cheap, radically-constrained persona agents in parallel populates the tails of that distribution, and that a lexical statistics step can cheaply separate genuine outlier signal from both dense consensus and incoherent noise — without needing embeddings.

This is an experiment, not a productionized creativity tool. Every run is disposable and inspectable: everything the pipeline produces lands in a run directory (see below) so a human can see exactly what happened at each stage, even when the final verdict is "no outliers found."

Do not over-trust early results. The filter (Stage 4) is validated on synthetic fixtures during its own build; whether it actually separates real swarm output is only established by the end-to-end validation run, and even that is provisional pending replication across multiple problems.

Invocation contract

Input: a problem statement (the thing to brainstorm about) and an optional requested swarm tier. If no tier is given, use the conservative default (see Cost Gate below).

Output: a run directory runs/<run-id>/ (see references/orchestration.md for the run-id convention) containing the full audit trail, and a final report.md presenting the conventional-wisdom baseline next to the synthesized emergent ideas — or, if no outliers survived filtering and retry, a coarse outcome report explaining why, with calibration and yield context attached so a human can root-cause it.

Do not fabricate a report when the pipeline produced no synthesizable outliers. A truthful "outliers not found" report is a valid outcome for an experiment testing an unvalidated premise.

Run directory and file schemas (the inter-stage contract)

Each run creates runs/<run-id>/ (gitignored — see .gitignore). The files below are not just logs: they are the pinned API contract between this skill, the swarm/council Workflows, and the Python steps under scripts/. Every stage reads its inputs from disk and writes its outputs to disk, even though the skill is the one driving each hand-off — this is what makes a run resumable and inspectable after the fact.

  • seeds.json — list of {id, persona, constraints, problem_slice, temperature, model} produced by Stage 1 seed assembly, plus a calibration-endpoint block {constraint_level, temperature, best_score, cleared} appended by the calibration loop. id (aliased persona_id/constraint_id downstream) is the join key every later stage dereferences back to full persona/constraint text. model is copied onto each seed from Stage 0's tier resolution (model_sequence[i]) — never re-derived in prose.
  • ideas.json — the swarm Workflow's collected output, written by the skill immediately after the Workflow(...) call returns: {ideas: [{text, persona_id, constraint_id, model}], scheduled, returned, by_model: {model: {scheduled, returned}}}. scheduled vs returned is yield telemetry; by_model breaks that same telemetry down per fleet model so a mixed opus/sonnet/haiku run's per-model yield is visible, not just the aggregate.
  • baseline.json{status, clusters, cluster_count, ...}: status is "ok" (at least one consensus cluster) or "no_consensus" (the degenerate baseline marker), and clusters holds Stage 4's consensus clusters with counts. The degenerate case is distinct from the blob case below and must be reported differently.
  • outliers.json{status, outliers}: status is "ok" (at least one outlier) or "no_outliers" (the explicit blob sentinel), and outliers is Stage 4's top-N most-isolated ideas with provenance ids preserved unchanged from ideas.json.
  • filter_detail.json — always written alongside baseline.json/ outliers.json: one row per raw idea (input order), {index, text, persona_id, constraint_id, model, survivor_index, duplicate_of, cluster_id, disposition, isolation, surprisal, rank_score}, where disposition is one of consensus / outlier / gated / isolated_below_topn / duplicate. Feeds report.html's data grid.
  • ledger.json — the single per-run agent-spend counter, owned and written by scripts/estimate.py (see Agent Ledger below). Never re-derive "how many agents has this run spawned" from prose.
  • council.json — written verbatim after Workflow({scriptPath: 'workflows/council.workflow.js', ...}) returns, then tallied in place by scripts/council.py tally: {candidates, round1, round2, abstentions, tally, top3, method, warnings}. See references/council.md for the full schema.
  • report.md — the final artifact: baseline vs. synthesized emergent ideas, or the outcome report when no outliers survived.
  • report.html — the self-contained Stage 6 run report (charts, council decision, sortable data grid), built by python scripts/report_html.py build --run-dir <dir> from every file above. Every input is optional-tolerant — a legacy run missing model provenance or council.json renders a "not produced this run" note, never a crash.
  • eval.json — written only by the offline eval/run_eval.py, never in the hot path.

Orchestration flow

The skill (this file, running as the main loop) drives every stage below in order. It is the caller of the Workflow(...) tool and the thing that shells out to the Python scripts under scripts/ — neither the workflow nor the Python steps invoke each other directly.

Stage 0: Cost gate

Before generating anything, resolve the requested tier against scripts/estimate.py's tier subcommand and get a go/no-go — see Agent Ledger below for why this is scripted rather than reasoned about in prose.

  • Tiers, not raw counts. size:N is gone. Request a t-shirt tier — s/small, m/medium, l/large, xl/huge — or a raw number, which resolves to whichever tier's fleet total is nearest (ties break to the smaller tier). Default, when none is given: s.
  • Fleet per tier (opus / sonnet / haiku / total): s = 1/3/10 (14); m = 2/6/20 (28); l = 4/12/40 (56); xl = 8/24/80 (112).
  • Resolve, don't re-derive. Run python scripts/estimate.py tier <spec> and take its JSON verbatim: {tier, fleet, total, model_sequence, gate, estimate}. model_sequence is the per-slot model assignment Stage 1 copies onto each seed; gate is the confirm/reject verdict against total; estimate now carries per-model pricing, not one blended number.
  • l and xl trip the confirm threshold (their totals, 56 and 112, exceed the ~50-agent threshold) — explicit user confirmation is required before any spawning happens, same existing rule, newly reachable at those tiers. The hard per-run ceiling (~200) is unchanged.
  • If the user declines to confirm, offer exactly two paths: proceed at the default tier (s), or abort. Never silently downgrade without saying so.
  • A tier that would push the per-run counter past the hard ceiling is refused outright, before any workflow launches.
  • Report the projected fleet and per-model estimate before the run starts, and the actuals (including Stage 3's per-model yield) after it ends.

This gate runs once, before calibration, because calibration batches, the main swarm, and any blob retry all decrement the same per-run counter.

Stage 1: Seed Assembly (U3)

Once the cost gate has passed, assemble seeds.json before anything is spawned. This is where R1 (distinct radical personas) and R2 (negative and forced constraints) actually happen. Draw from references/personas.md. Concretely, for the confirmed tier's fleet total:

  • Pick that many distinct personas, inventing fresh variations in the same register when the tier exceeds the library.
  • Attach constraints independently of persona — a banned-buzzword rotation, a forced material/budget/format constraint, and the length cap matching R5's one-or-two-sentence floor, rotated per seed.
  • Write a fresh problem_slice per seed, self-contained in that persona's frame — the only problem context that seed's agent ever sees.
  • Vary temperature per seed, biased higher for further-out personas.
  • Assign each seed a model by copying model_sequence[i] from Stage 0's tier resolution onto seed i, in order — scripted arithmetic, never hand-picked per persona.

Calibration's probe batch (below) stays haiku regardless of any given seed's assigned model: a probe measures constraint-induced lexical diversity, not model quality, and haiku is the modal fleet member at every tier, so a constant probe model keeps escalation scores comparable across runs. Concretely, the calibration loop slices its batch from seeds.json's haiku-assigned seeds, not an arbitrary N-slice of the full seed list.

The result is written to seeds.json as {id, persona, constraints, problem_slice, temperature, model} objects — see personas.md's "Assembling seeds.json" section for the exact shape and a worked example.

Seed assembly itself is pure text generation, not agent spawning, so it does not touch the per-run counter.

Calibration Loop (U6)

Once seeds.json exists, before spending the full swarm's budget, run one small calibration batch and check whether it is actually diverse. This is R3: measure output similarity with the same statistical engine as Stage 4 (KTD5) and tighten constraints / raise temperature until it clears a floor, bounded by a try cap (KTD10).

The loop, each iteration:

  1. Launch a small calibration batch. Invoke Workflow({scriptPath: 'workflows/swarm.workflow.js', args: {...}}) with a size-N slice of seeds.json's haiku-assigned seeds (N smaller than the full swarm — just enough ideas to read variance from; see Stage 1 above for why the slice is haiku-only). This spawn decrements the shared per-run counter exactly like any other swarm launch.
  2. Score it. Shell out to scripts/calibrate.py against the batch's collected idea texts. calibrate.py reports a scalar diversity score — mean isolation across the batch — composed on stats.py's primitives exactly as filter.py's own near-duplicate collapse computes similarity. Result carries a verdict of "proceed" or "tighten".
  3. Consume a try, unconditionally, before branching on the verdict — including a degenerate batch.
  4. Branch:
    • "proceed" — exit the loop.
    • "tighten" with tries remaining — escalate constraints/temperature, regenerate seeds.json at the new level, go back to step 1.
    • "tighten" with no tries remaining — exit without clearing the floor; record it honestly.

On exit, append the calibration endpoint to seeds.json: {constraint_level, temperature, best_score, cleared}.

Stage 3: Swarm generation

Once seeds have cleared calibration (or its try-cap is spent), run the swarm via Workflow({scriptPath: 'workflows/swarm.workflow.js', args: {...}}). Every seed fans out on its own assigned model — a mixed fleet, not one uniform model — via the workflow's resolveModel precedence: a seed's own model field wins if it names a known fleet model, falling back to args.model (used only when a seed lacks a valid model of its own), and finally to haiku. The skill passes seeds.json (each seed carrying its model), the confirmed tier's total, and the problem statement through args — it does not regenerate the workflow script per run (see references/orchestration.md for workflow-authoring conventions).

The swarm's collected ideas come back in-band, as the Workflow(...) tool result. The skill's job immediately after the call returns is to persist that result verbatim to ideas.json — this is what turns the run into a resumable checkpoint.

Each spawned swarm agent counts against the per-run counter from Stage 0.

Stage 4: Filter

With ideas.json written, shell out to scripts/filter.py against that file. filter.py collapses near-duplicates, extracts consensus clusters as the baseline, and ranks the remainder by isolation — embedding-free by default (see references/filtering.md). The skill's role is purely to invoke the script and read back its outputs:

  • baseline.json — always written, even when degenerate.
  • outliers.json — always written, even when empty (the blob case).
  • filter_detail.json — always written; carries each idea's model forward from ideas.json (see Run directory schemas above).

If outliers.json is empty, do not proceed to synthesis. Hand off to blob retry instead.

Blob Retry (U7)

On the "no_outliers" sentinel: escalate constraints/temperature, regenerate seeds.json (re-applying the same tier's model_sequence), and re-run the swarm + filter directly, skipping calibration. Each iteration decrements the retry try-counter and spends the shared counter (estimate.py spend ... --stage retry) before anything else — a spend denial stops the loop even with tries left; full mechanics in references/orchestration.md's Blob Retry section.

Exit on a non-empty outliers.json (hand off to Stage 5), or on exhausting the try cap or counter. On exhaustion, skip synthesis and council, and write the outcome report into report.md: outliers not found, which limit stopped it, calibration's cleared flag, and the final attempt's yield telemetry.

Synthesis Orchestration (U8)

Once Stage 4 (or Blob Retry) has produced a non-empty outliers.json, the skill runs Stage 5: feasibility-filter the outliers, then synthesize whatever survives into report.md. Full rubric and pinned artifact format live in references/synthesis.md; this is the orchestration summary.

The skill reads outliers.json and baseline.json itself, then delegates judgment to a single heavyweight agent call — coordinator roles (synthesis, validators, aggregators, judges, council) omit model entirely and inherit whatever model the surrounding companion/orchestrator session is already running on, rather than pinning a tier — prompted as the harsh critic synthesis.md specifies. This is a single delegated call, not a Workflow(...) fan-out, since Stage 5 evaluates one outlier set as a whole and needs its result written to disk. That call applies synthesis.md's feasibility rubric (impossible / hallucinated / word-salad) to every outlier before any synthesis work (R19), then synthesizes survivors into named strategies with provenance preserved (R20). The skill then assembles report.md in synthesis.md's pinned section order — Baseline, Emergent Ideas, Council Decision, Discarded Outliers, Run Context (R21).

Council Stage

Once report.md's Baseline/Emergent Ideas content is assembled, the skill runs a three-councilor, two-round deliberation over the fixed candidate set (baseline clusters, outliers, any synthesized strategies), judged purely on novelty and feasibility, then tallies it deterministically. Full method, prompts, schemas, and the Borda tally live in references/council.md.

  • Ledger spend-first. Before calling the workflow: python scripts/estimate.py spend <run_dir> 6 --stage council (three councilors × two rounds). A denial skips council entirely — no workflow call — and the report must say plainly council was skipped and why.
  • Also skipped on blob-retry exhaustion — no outlier candidates exist to rank; skip and say so, same as Stage 5's degenerate-baseline handling.
  • Invoke. Workflow({scriptPath: 'workflows/council.workflow.js', args: {candidates, problem}}). Every councilor agent in both rounds omits model (coordinator role, see Synthesis above) and inherits the active session model.
  • Persist, then tally. Persist {round1, round2, abstentions} verbatim into council.json alongside the candidates list, then run python scripts/council.py tally --run-dir <dir> for the deterministic Borda tally — the workflow never scores anything; council.py never talks to a model.

Report + Artifact

Whichever path Stage 5, Council, or blob-retry-exhaustion took, the skill's last actions:

  1. Build report.html: `python scripts/report_html.py build --run-dir
  2. Publish it via the Artifact tool for a viewable link, best-effort — on failure, fall back to printing the file's absolute path.
  3. Print the chat report, this exact skeleton, every number read from the run's own JSON files (never re-derived):
## Swarm Brainstorm — <problem>
**Run** `<run-id>` | Tier **<s|m|l|xl>** (<o> opus / <s> sonnet / <h> haiku) |
Yield <returned>/<scheduled> | Ledger <count>/<ceiling> agents

### Council decision (top 3)
1. **<title>** (`<id>`, Borda <n>) — <digest of councilor justifications>
…

### 10 most novel ideas
| # | Idea | Novelty | Models | Agents |
|---|------|---------|--------|--------|
| 1 | <short title> | <rank_score 2dp> | haiku×2, sonnet×1 | 3 |

**Artifacts:** [report.html](<artifact link or path>) · `report.md` · `runs/<run-id>/`

Novelty is the filter's rank_score; Models/Agents come from each outlier's models/agent_count fields. Fewer than 10 outliers: render what exists and say so. Council skipped: that section reads Council skipped: <reason> instead of a top-3 list.

Offline evaluation hand-off

Separately from the hot path above, a completed run can be scored by eval/run_eval.py (built in U9) — an explicit, user-initiated follow-up, never automatically triggered. It reads ideas.json and outliers.json from an existing run directory and writes eval.json back into it. Mention this hand-off once a run's report.md is ready; do not run it unprompted.

Agent ledger

The per-run agent-spend counter is arithmetic that an LLM should not be trusted to track in prose across a multi-stage run. It is scripted in scripts/estimate.py, exposing deterministic spend()/check() functions. The skill calls these before every spawn — Stage 0's initial gate, each calibration batch, the main swarm, any blob retry, the Council stage (n=6, spent before its Workflow(...) call), and Synthesis (n=1) — rather than reasoning about remaining budget in prose. Council's and Synthesis's spends are new as of the tiered-fleet/council revision: a run predating it has a smaller ledger total for the same stage sequence, and that is expected, not a discrepancy to chase down. The running count persists in ledger.json so it can be inspected after the fact.

Separately from the per-run counter: this skill's agent spawns also draw against the Workflow runtime's session-lifetime cap (currently 1000 agents, shared across the session). There is no persisted cross-run counter for this yet. Watch for that cap in practice and stop launching new runs as the session approaches it.

References

  • references/orchestration.md — workflow-authoring conventions, the run-id convention, budget-partition detail, and loop guidance referenced throughout this file.
  • references/personas.md (U3) — persona and constraint seed library.
  • references/filtering.md (U2) — Stage 4 filter method detail.
  • references/synthesis.md (U8) — Stage 5 synthesis prompt and artifact format.
  • references/council.md — Council stage method, prompts, schemas, and the deterministic Borda tally.