Dokumentation durchsuchen

Schwärme aus Sub-Agenten

Wann ein Panel, eine Jury oder ein Fanout von Sub-Agenten sinnvoll ist, die vier Dateien dahinter, Austeilen mit Seed, das Budget von 26, ehrliche Auswertungen und ein durchgespieltes Käuferpanel.

Auf dieser Seite
  1. Wann ein Schwarm sinnvoll ist
  2. Der Ablauf von Anfang bis Ende
  3. Das Budget, die Wellen und die Freigabe
  4. Die vier Dateien, Feld für Feld
  5. Deterministisches Austeilen und Seeds
  6. Abgelehnte Antworten und was nie geschieht
  7. Die Ehrlichkeitsregeln
  8. Ein durchgespieltes Käuferpanel
  9. Die Schritte des Abnahmeprotokolls, erneut ausgeführt: 1 gültige Antwort von 30
  10. Eine Jury: drei Blickwinkel auf denselben Pitch
  11. Einsatzfälle für Panel und Jury
  12. Laufstruktur und Grenzen

Ein Schwarm (swarm) besteht aus vielen Sub-Agenten, die je einmal dieselbe Art Arbeit leisten: dreißig simulierte Käufer, die einen Pitch lesen, drei Juroren, die ihn je durch eine Linse lesen, ein Autor pro Seite einer Website. Moderator ist dein Assistent; er erledigt nie die Arbeit einer Einheit. bmad-plus swarm führt Buch: Es validiert die Dateien, teilt die Einheiten aus, schreibt ein Briefing pro Sub-Agent, prüft jede Antwortdatei und zählt nur die gültigen. Es ruft nie ein Modell auf, öffnet keine Netzwerkverbindung und startet keinen Prozess. Diese Seite richtet sich an alle, die eine Botschaft, eine Seite oder einen Plan an vielen Lesern testen oder wiederkehrende Arbeit im Budget auf Sub-Agenten verteilen wollen.

Erst fragen, dann der Schwarm Die Intake-Fragen, das Budget von 26 und die Freigabe, Wellen von Sub-Agenten und eine Auswertung, die klarstellt, dass simulierte Einheiten keine Menschen sind.
Transkript

Bevor ein Pack handelt, fragt es. Der Intake stellt jeweils ein paar Fragen und markiert die Pflichtfragen. Wo du keine Antwort hast, schlägt es einen Standardwert vor oder hält die Frage als unbekannt fest, samt Risiko. Die Antworten werden zu einem Briefing, und nichts darin ist erfunden. Dann der Schwarm. Standardmäßig darf ein Lauf 26 Sub-Agenten nutzen, bevor der Assistent dich fragen muss. Willst du mehr, wartet der Lauf mit dem Status needs-approval, bis ein Mensch zustimmt. Nach der Freigabe arbeiten die Sub-Agenten standardmäßig in Wellen von zehn, jeder liest ein Briefing und schreibt eine Antwort. Die Laufzeit prüft jede Antwortdatei und zählt nur die gültigen. Diese Auswertung besteht aus Demodaten und beginnt mit ihrem Hinweis: Simulierte Einheiten sind keine Menschen. Lies die Raten als Obergrenze und bestätige sie mit echten Menschen.

Transkript mit Bildbeschreibung

Warnung Simulierte Einheiten sind keine Menschen

Ein Panel liefert die Lesart eines Modells, das Käufer spielt. Behandle seine Raten als Obergrenze, die mit echten Menschen zu bestätigen ist, und seine Zitate als das, was eine simulierte Einheit geschrieben hat, nie als Testimonials oder Nutzerinterviews. Jede Auswertung beginnt mit diesem Satz.

Wann ein Schwarm sinnvoll ist

Die drei Arten von Schwarm
ArtDie Einheiten stammen ausTypischer EinsatzWas die Auswertung zeigt
panelEin Profil: Die Einheiten werden nach exakten Quoten aus einem Seed ausgeteilt.Simulierte Käufer, Leser oder Nutzer, die einen Pitch, einen Preis, eine Seite lesen.Eine Rate je Gruppe, Zählungen, wörtliche Zitate, Zahlen.
juryEine Liste in der Definition: eine Einheit pro Eintrag, jede mit einem lens.Eine kritische Gegenlesung eines Pitches, einer Seite oder eines Plans, ein Blickwinkel pro Juror.Zählungen und Zitate je Blickwinkel.
fanoutEine Einheitendatei, die du beim Init schreibst: eine Einheit pro Eintrag, jede mit disjunktem Schreib-scope.Zu schreibende Seiten, zu dokumentierende Module, vorzubereitende Szenen, je ein Sub-Agent.Eine Rate und Zahlen; als dauerhafter Nexus-Plan exportierbar.

Ein Panel und eine Jury laufen als Sitzungs-Sub-Agenten: Dein Assistent startet sie, wartet und liest ihre Dateien. Ein Fanout kann genauso laufen oder mit swarm plan als dauerhafter Nexus-Plan exportiert werden, wenn die Arbeit die Sitzung überleben muss, pro Einheit eine unabhängige Prüfung braucht oder das Repository ändert.

Wann nicht

  • Wenn du echte Menschen fragen kannst. Ein Schwarm probt; er misst nicht.
  • Bei zwei oder drei Aufgaben. Frage den Agent direkt oder nutze parallel von Nexus.
  • Bei Arbeit, in der ein Ergebnis vom anderen abhängt. Einheiten sind konstruktionsbedingt unabhängig.
  • Um kostenpflichtige Medien zu erzeugen. Bild-, Video- und Audioerzeugung deckt das Budget nie ab: Der Assistent fragt jedes Mal.

In 0.23.0 liefert kein Pack eine Schwarm-Definition: Laufzeit und Moderations-Skill gehören zu Core, und die auf dieser Seite verwendeten Definitionen sind Testfixtures im BMAD+-Repository (tests/fixtures/swarm/). Die Definition liefert ein Pack oder du. Diese Dateien sind nicht im npm-Paket enthalten; diese Seite zeigt jede vollständig, sodass du sie unverändert anlegen kannst.

Der Ablauf von Anfang bis Ende

Dateien und Befehle
definition + profile|list|units + context
        |
      init ---- over budget? exit 2 "needs approval": ask a human, re-run with --approved
        |
   cards.json  (frozen)
        |
     briefs ---- one brief per unit, in waves
        |
  one sub-agent per brief  ->  answers/<unit>.json
        |
      check ---- missing / invalid, with reasons
        |  (second chance once; save files a printed reply)
      tally ---- tally.json + tally.md, disclosure first

  1. init

    Validiert die Definition, das Profil bzw. die Einheitendatei, die Kontextdateien und die Briefing-Vorlage; teilt die Karten aus oder listet sie; wendet das Budget an. Ein Panel braucht --n (1 bis 1000); der Seed wird gezogen und festgehalten, wenn du keinen angibst. Ein Lauf über dem Budget endet hier mit Exit-Code 2.

    Im Terminal deines Projekts
    npx bmad-plus swarm init --definition swarm/buyer-panel.json --profile swarm/profile.json --context pitch=swarm/pitch.md --n 30 --seed 7

  2. briefs

    Rendert ein Briefing für jede Einheit ohne gültige Antwort aus der eingefrorenen Vorlage, der Karte und den eingefrorenen Kontexten und druckt die Wellen (10 Einheiten pro Welle, sofern --wave nichts anderes sagt) mit dem Briefing-Pfad jeder Einheit.

    Im Terminal deines Projekts
    npx bmad-plus swarm briefs RUN

  3. Eine Welle starten

    Dein Assistent startet pro Briefing einen Sub-Agenten mit genau einer Anweisung: das Briefing lesen und genau befolgen; es ist die gesamte Anweisung. Er fasst das Briefing nicht zusammen, ergänzt keinen Kontext und führt nie zwei Einheiten in einem Sub-Agenten zusammen. Er wartet auf die ganze Welle, bevor die nächste startet.

  4. check

    Listet jede Einheit mit fehlender oder ungültiger Antwort samt Grund. Exit-Code 0, wenn alle Einheiten gültig sind, sonst 1.

    Im Terminal deines Projekts
    npx bmad-plus swarm check RUN

  5. Eine zweite Chance, einmal

    Führe briefs erneut aus (es rendert nur Einheiten ohne gültige Antwort) und starte diese Einheiten neu. Eine Einheit, die ihre Antwort ausgegeben statt geschrieben hat, wird mit save RUN UNIT --input FILE abgelegt, wobei die Datei die Antwort dieser Einheit wörtlich enthält. Eine Einheit, die nach der zweiten Welle fehlt, bleibt fehlend.

    Im Terminal deines Projekts
    npx bmad-plus swarm save RUN B005 --input swarm-inbox/B005.txt

  6. tally

    Zählt nur gültige Antworten und schreibt tally.json und tally.md. Einheiten ohne gültige Antwort werden als übersprungen aufgeführt und in der Nennerzeile mitgezählt. Der Offenlegungshinweis ist die erste Zeile von tally.md.

    Im Terminal deines Projekts
    npx bmad-plus swarm tally RUN

  7. plan (nur Fanout)

    Statt die Sub-Agenten in der Sitzung auszuführen, wird der Fanout als Nexus-Plan exportiert. Siehe die Nexus-Seite.

    Im Terminal deines Projekts
    npx bmad-plus swarm plan RUN --out .bmad-plus/swarm/reports/RUN/plan.json

swarm inspect RUN zeigt jederzeit den Zustand eines Laufs (Einheiten, mit Briefing, gültig, ungültig, fehlend) und schreibt nichts. Exit-Codes: 0 erledigt, 2 needs-approval (zuerst muss ein Mensch Ja sagen), 1 unvollständig oder Fehler. Mit --json trägt jede Ausgabe schemaVersion: 1 und einen status.

Das Budget, die Wellen und die Freigabe

Drei Schlüssel im Block swarm von _bmad/config.yaml setzen die Grenzen. Der Installer schreibt den Block mit seinen Standardwerten; ein von einer früheren Version aktualisiertes Projekt hat keinen Block und bekommt dieselben Standardwerte.

Der swarm-Block
SchlüsselStandardBedeutung
budget26Sub-Agenten, die ein Lauf nutzen darf, bevor der Assistent dich fragen muss. Ganzzahl von 1 bis 1000.
wave10Gleichzeitig gestartete Sub-Agenten. Der Assistent wartet auf eine Welle, bevor die nächste startet. Ganzzahl von 1 bis 1000.
media_creditsaskKostenpflichtige Erzeugung (Bilder, Video, Audio) wird nie von einem Budget freigegeben. Einziger erlaubter Wert ist ask.

Ist n größer als das Budget und fehlt --approved, legt init den Lauf mit dem Status needs-approval an, endet mit 2 und schreibt kein Briefing. Der Assistent stellt dir einen Satz mit der Zahl („Dieses Panel braucht 30 Sub-Agenten; das Budget ist 26. Starten?“). Erst nach deinem Ja führt er init mit --approved und demselben Seed erneut aus. Er übergibt --approved nie nach eigenem Ermessen. Der abgelehnte Lauf ist endgültig: Spätere Befehle darauf antworten needs-approval und schreiben nichts.

Abgelehnt, dann freigegeben: ein Panel von 30 bei Budget 26
npx bmad-plus swarm init --definition swarm/buyer-panel.json --profile swarm/profile.json --context pitch=swarm/pitch.md --n 30 --seed 7
buyer-panel-20261019-g1i9: needs approval. The run needs 30 sub-agents and the budget is 26: ask the user, then re-run init with --approved --seed 7.
Exit-Code 2. Es wurde kein Briefing geschrieben.
npx bmad-plus swarm init --definition swarm/buyer-panel.json --profile swarm/profile.json --context pitch=swarm/pitch.md --n 30 --seed 7 --approved
buyer-panel-20261019-vqkf: panel of 30 units, budget 26, approval user.
Seed 7 (same seed, same cards).
Next: bmad-plus swarm briefs buyer-panel-20261019-vqkf

Ausgabe eines echten Laufs. Quelle: bmad-plus 0.23.0, 2026-10-19

Die vier Dateien, Feld für Feld

Die Laufzeit lehnt ein unbekanntes Feld, einen falschen Typ und eine Grenzverletzung ab; sie rät nie. Jeder Pfad ist projektrelativ mit / als Trenner. Der Pfad der Briefing-Vorlage ist relativ zur Definitionsdatei.

1. Die Definition (JSON)

Felder der Definition
FeldRegel
schemaVersionMuss 1 sein.
id1 bis 64 Kleinbuchstaben, Ziffern oder -. Eröffnet die Lauf-ID.
kind und units.sourceDas Paar muss zusammenpassen: panel mit profile, jury mit list, fanout mit input.
units.idPrefix1 bis 4 Buchstaben. Pflicht beim Panel; optional bei einer Jury, deren Einträge keine id haben; fehlt beim Fanout.
units.listNur Jury: 1 bis 1000 Einträge, jeder mit einem Text lens und weiteren Text-, Zahlen- oder Boolean-Feldern; eine optionale id.
packOptionale Pack-ID, im Lauf festgehalten.
titleÜberschrift der Auswertung.
brief.templateEinfacher relativer Pfad zu einer Markdown-Datei, ohne .- oder ..-Teile.
brief.contextNamen der Kontextdateien, die der Moderator beim Init übergeben muss (--context NAME=FILE). Jede ist Pflicht; höchstens 20.
answer.requiredFelder, die vorhanden sein müssen. id ist implizit und immer Pflicht.
answer.fieldsHöchstens 50 Felder, jedes typisiert (siehe nächste Tabelle). Ein Sub-Agent darf kein nicht deklariertes Feld schreiben.
tallyrate (ein Boolean-Feld), groupBy (bis zu 5 Kartenfelder, die jede Karte trägt), counts (Enum-Felder), quotes (Textfeld auf je Gruppe behaltene Zitate, 1 bis 10), numbers (Integer- oder Zahlenfelder).
disclosure1 bis 500 Zeichen, in jeder Auswertung und in der Ausgabe von briefs zuerst gedruckt.
Typen der Antwortfelder
TypOptionenAkzeptierter Wert
booleankeinetrue oder false.
integermin, maxEine ganze Zahl innerhalb der Grenzen.
numbermin, maxEine beliebige Zahl innerhalb der Grenzen.
stringmin, max (Länge)Text; standardmäßig 0 bis 4000 Zeichen, Obergrenze 20000; min wird am getrimmten Text geprüft.
enumvalues (1 bis 50, verschieden)Einer der aufgeführten Werte.
listmaxItems (Standard 50, Obergrenze 200)Eine Liste nicht leerer Texte, je bis zu 1000 Zeichen.

2. Das Profil (nur Panel)

Felder des Profils
FeldRegel
subject, targetWas beurteilt wird und wer urteilt. Dokumentation für Leser der Datei.
dimensions1 bis 10 Dimensionen, jede mit einem name und 1 bis 50 values. Die Anteile einer Dimension ergeben zusammen 1.
values[].value, shareDas Label eines Werts und sein Anteil am Panel.
values[].rangesOptionale numerische Bereiche, die beim Austeilen dieses Werts gezogen werden, etwa "income": [38000, 85000]. Jeder Wert einer Dimension deklariert dieselben Bereichsnamen.
values[].noteOptionaler Satz. Er wird zum Kartenfeld <dimension>_note (leer bei Werten ohne Notiz).
ranges (oberste Ebene)Bereiche, die einmal pro Karte gezogen werden. Ganzzahlige Grenzen ergeben Ganzzahlen; andere Grenzen Zahlen mit zwei Nachkommastellen.
poolsBenannte Satzlisten. Pro Karte wird ein Eintrag jedes Pools ausgeteilt.

Kartenfelder sind die Dimensionsnamen, ihre Bereichsnamen, die Bereichsnamen der obersten Ebene, die Pool-Namen und die Notizen. Namen müssen verschieden sein, und id, scope und lens sind reserviert. Personennamen werden nicht ausgeteilt: Ein Briefing, das einen braucht, zieht ihn aus einem vom Pack gelieferten Pool.

3. Die Einheitendatei (nur Fanout)

swarm/units.json
{
  "schemaVersion": 1,
  "units": [
    { "id": "about", "scope": "site/about", "title": "About us", "tone": "warm" },
    { "id": "pricing", "scope": ["site/pricing", "site/data/prices.json"], "title": "Pricing", "tone": "plain" },
    { "id": "contact", "scope": "site/contact", "title": "Contact", "tone": "short" }
  ]
}

  • id: 1 bis 64 Kleinbuchstaben, Ziffern, _ oder -. Sie wird zur Nexus-Task-ID.
  • scope: ein Pfad oder eine Liste von bis zu 20, portabel und projektrelativ, nie .git oder .bmad-plus. Scopes sind paarweise disjunkt: Keiner darf einen anderen enthalten.
  • Jedes andere Feld muss Text, Zahl oder Boolean sein; es wird zu einem Kartenfeld, im Briefing als {{card.field}} verfügbar.

Die Definition zu dieser Einheitendatei hat kein Profil; init nimmt die Einheiten mit --units, zum Beispiel npx bmad-plus swarm init --definition swarm/page-fanout.json --units swarm/units.json. Hier die Definition des Fanouts site-pages aus dem Beispiel am Ende dieser Seite, danach ihre Briefing-Vorlage.

swarm/page-fanout.json (die Definition)
{
  "schemaVersion": 1,
  "id": "site-pages",
  "kind": "fanout",
  "title": "One sub-agent per page of the site",
  "units": { "source": "input" },
  "brief": { "template": "briefs/page.md", "context": [] },
  "answer": {
    "required": ["id", "done", "words"],
    "fields": {
      "done": { "type": "boolean" },
      "words": { "type": "integer", "min": 0 },
      "note": { "type": "string", "max": 200 }
    }
  },
  "tally": { "rate": "done", "numbers": ["words"] },
  "disclosure": "Each page was written by a separate sub-agent from the same brief; read them together before publishing."
}

swarm/briefs/page.md (die Vorlage)
# Page {{unit.id}}

Write the page "{{card.title}}" under `{{card.scope}}`, {{card.tone}} in tone. Touch nothing
outside that folder.

When the page is written, write a JSON object to `{{answer.path}}` with `id` ("{{unit.id}}"),
`done`, `words` (the word count) and an optional `note`.

{{disclosure}}

4. Die Briefing-Vorlage (Markdown) und die Kontexte

Platzhalter: nichts anderes ist zwischen doppelten Klammern erlaubt
PlatzhalterErgibt
{{card.<field>}}Das Kartenfeld; eine Liste wird kommagetrennt ausgegeben.
{{context.<name>}}Die beim Init übergebene Kontextdatei, wörtlich und im Lauf eingefroren.
{{answer.path}}Der absolute Pfad der Antwortdatei, die der Sub-Agent schreiben muss.
{{run.id}}, {{unit.id}}Die Lauf-ID und die Einheiten-ID.
{{disclosure}}Der Offenlegungshinweis der Definition.

Warnung Die Laufzeit filtert nichts

Kartenwerte, Pool-Einträge, Felder gelisteter Einheiten und Kontextdateien erreichen den Sub-Agenten Wort für Wort. Ein Pool-Eintrag, der wie eine Anweisung klingt, landet im Briefing als Anweisung. Das Pack verantwortet seine Pools, Einheitenfelder und Vorlagen; du verantwortest die Kontexte, die du übergibst. Lies einen Kontext, bevor du ihn übergibst, und übergib nie eine Datei, die du nicht gelesen hast: Sie steht in jedem Briefing, samt Geheimnissen und Anweisungen. Ein unbekannter Platzhalter, ein Kartenfeld, das einer Karte fehlt, ein nicht deklarierter Kontext oder ein literales {{ in der Vorlage lassen init scheitern.

Deterministisches Austeilen und Seeds

Dasselbe Profil, dasselbe --n und derselbe --seed ergeben immer dieselben Karten. Jede Dimension wird nach exakter Quote verteilt (größter Rest, Gleichstand nach Deklarationsreihenfolge): Bei Anteilen von 0,45, 0,40 und 0,15 enthalten zwanzig Karten 9, 8 und 3 Einheiten dieser Werte, egal welcher Seed. Die Wertespalte wird dann von einem SHA-256-basierten Generator gemischt, und Karte k nimmt die Position k jeder Spalte; Bereiche und Pool-Einträge folgen der Reihe nach. Der Seed (0 bis 2147483647) steht in run.json.

Das macht einen Vorher-nachher-Vergleich ehrlich. Um zwei Fassungen eines Pitches zu testen, führst du dasselbe Profil mit demselben --n und --seed aus und änderst nur die Kontextdatei: Die Käufer sind dieselben, geändert hat sich nur der Pitch. Einheiten-IDs sind das Präfix plus die auf mindestens drei Stellen aufgefüllte Position (B001, B030, B1000).

Abgelehnte Antworten und was nie geschieht

Eine Antwort zählt nur, wenn answers/<unit>.json eine reguläre Datei ist, als JSON-Objekt gelesen wird, eine id gleich der Einheiten-ID und alle Pflichtfelder trägt, kein unbekanntes Feld deklariert und jeden Typ und jede Grenze erfüllt. check meldet eine Einheit als missing (keine Datei) oder invalid (mit Gründen). save wendet dieselben Regeln auf das erste ausgewogene JSON-Objekt in einer ausgegebenen Antwort an und lehnt ab, wenn keines gefunden wird, wenn die Validierung scheitert (auch eine falsche id), wenn die Einheit schon eine gültige Antwort hat und bei einem Lauf, der noch eine Freigabe braucht. Eine abgelehnte Antwort ändert nichts auf der Platte.

Eine Antwort wird abgelegt, eine andere abgelehnt
npx bmad-plus swarm save buyer-panel-20261019-2ftt B005 --input swarm-inbox/B005.txt
buyer-panel-20261019-2ftt: answer of B005 filed at /work/demo/app/.bmad-plus/swarm/runs/buyer-panel-20261019-2ftt/answers/B005.json
npx bmad-plus swarm save buyer-panel-20261019-2ftt B006 --input swarm-inbox/B006.txt
Swarm: Reply of unit B006 refused: field "buys" must be true or false.
Die erste Datei enthält einen Satz gefolgt von einem gültigen JSON-Objekt; die zweite ein Objekt, dessen Feld buys der Text „maybe“ ist. Exit-Codes 0 und 1.

Ausgabe eines echten Laufs. Quelle: bmad-plus 0.23.0, 2026-10-19

Die Ehrlichkeitsregeln

  • Nie für eine Einheit antworten: weder durch Schreiben einer Antwortdatei noch durch „Reparieren“ einer ungültigen noch durch Ablegen mit save von etwas, das ein Sub-Agent nicht ausgegeben hat.
  • Nie ein Briefing bearbeiten. Eine Änderung gehört in die Vorlage oder die Definition und dann in einen neuen Lauf.
  • Der Offenlegungshinweis kommt einmal und zuerst: Die Auswertung beginnt damit, und der Assistent wiederholt ihn einmal in seinem Bericht, vor jeder Zahl.
  • Raten sind eine Obergrenze, die mit echten Menschen zu bestätigen ist. Zitate sind das, was eine simulierte Einheit geschrieben hat.
  • Der Seed reist mit dem Ergebnis: gleicher Seed, gleiche Karten, damit ein Vergleich ein Vergleich ist.
  • Eine gültige Antwort ist eine wohlgeformte. Nichts beweist, dass ein Sub-Agent sein Briefing gelesen, in seiner Karte geblieben oder die Wahrheit gesagt hat; Qualität ist deine Lesart der Auswertung.
  • Antworten werden von außerhalb des Zustandsbaums abgelegt: save --input nimmt eine vom Host geschriebene Projektdatei (etwa in swarm-inbox/), nie einen Pfad unter .bmad-plus/.

Ein durchgespieltes Käuferpanel

Das Szenario: Eine Kaffeebar namens Orbit will wissen, wie ein urbaner Berufstätiger auf ihren Pitch reagiert. Die Dateien unten sind die Test-Fixtures des BMAD+-Repositorys, hier unverändert verwendet: die Definition, das Profil und die Briefing-Vorlage. Der Pitch selbst besteht aus zwei Sätzen.

swarm/buyer-panel.json (die Definition)
{
  "schemaVersion": 1,
  "id": "buyer-panel",
  "kind": "panel",
  "pack": "marketfit",
  "title": "Simulated buyers see the pitch",
  "units": { "source": "profile", "idPrefix": "B" },
  "brief": { "template": "briefs/buyer.md", "context": ["pitch"] },
  "answer": {
    "required": ["id", "buys", "reason_code", "reason"],
    "fields": {
      "buys": { "type": "boolean" },
      "reason_code": { "type": "enum", "values": ["price", "habit", "need", "trust", "other"] },
      "reason": { "type": "string", "max": 600 },
      "price_floor": { "type": "number", "min": 0 },
      "visits_per_week": { "type": "integer", "min": 0, "max": 14 },
      "would_tell": { "type": "list", "maxItems": 3 }
    }
  },
  "tally": {
    "rate": "buys",
    "groupBy": ["segment", "behaviour"],
    "counts": ["reason_code"],
    "quotes": { "reason": 2 },
    "numbers": ["price_floor"]
  },
  "disclosure": "Simulated units are not people. Read rates as an upper bound and confirm with real ones."
}

swarm/profile.json (das Profil)
{
  "schemaVersion": 1,
  "subject": "Orbit espresso bar",
  "target": "Urban professionals who buy coffee most days",
  "dimensions": [
    {
      "name": "segment",
      "values": [
        { "value": "early career", "share": 0.45, "ranges": { "income": [38000, 85000] } },
        { "value": "mid career", "share": 0.4, "ranges": { "income": [85000, 150000] } },
        { "value": "high earner", "share": 0.15, "ranges": { "income": [150000, 210000] } }
      ]
    },
    {
      "name": "behaviour",
      "values": [
        { "value": "daily regular", "share": 0.2, "note": "same drink, same place, most mornings" },
        { "value": "explorer", "share": 0.5 },
        { "value": "occasional", "share": 0.3, "note": "a treat, not a routine" }
      ]
    }
  ],
  "ranges": { "age": [24, 38], "walk_minutes": [1.5, 12] },
  "pools": {
    "objection": ["too steep for a drink", "my place is closer", "I do not know the brand"],
    "habit": ["you pass the street on the way to work", "you order the same thing every day"]
  }
}

swarm/briefs/buyer.md (die Vorlage)
# You are unit {{unit.id}} of run {{run.id}}

You are one simulated buyer. Stay inside this card for the whole task.

- Segment: {{card.segment}}, income {{card.income}}
- Behaviour: {{card.behaviour}} ({{card.behaviour_note}})
- Age {{card.age}}, {{card.walk_minutes}} minutes on foot from the bar
- Your first objection: {{card.objection}}
- Your habit: {{card.habit}}

## The pitch

{{context.pitch}}

## Your answer

Write a JSON object to `{{answer.path}}` with the fields `id` (exactly "{{unit.id}}"), `buys`,
`reason_code` (price, habit, need, trust or other), `reason` (your own words, 600 characters at
most) and, when you have one, `price_floor`.

{{disclosure}}

swarm/pitch.md (der Kontext)
Orbit opens at 7, two streets from the station. A flat white is 4.20, the loyalty card gives
the tenth one free, and the bar keeps your usual order under your name.

Seed 7 und 30 Einheiten ergeben diese erste Karte (aus cards.json). Das Briefing, das der Sub-Agent erhält, ist die Vorlage mit dieser Karte, dem Pitch und dem Antwortpfad.

Die Karte der Einheit B001
{
  "id": "B001",
  "segment": "mid career",
  "income": 114720,
  "behaviour": "occasional",
  "behaviour_note": "a treat, not a routine",
  "age": 32,
  "walk_minutes": 8.99,
  "objection": "I do not know the brand",
  "habit": "you order the same thing every day"
}

Im Protokoll unten würde der Assistent 30 Sub-Agenten in drei Wellen starten. Um die Dateien, das Werkzeug und die Auswertung ohne Modell zu zeigen, wurden fünf Antworten für diese Demonstration von Hand geschrieben (vier als Dateien, eine über save), und eine sechste Antwort wurde abgelehnt. Die Auswertung zählt also 5 von 30 Einheiten und nennt die anderen 25. Die Zitate unten stammen daher ebenfalls nicht von einem Modell: Sie sind Demonstrationstext.

Die Demonstrationsantworten (je eine Datei in answers/; B005 und B006 sind mit save abgelegte Antworten)
answers/B001.json    { "id": "B001", "buys": true, "reason_code": "habit", "reason": "The bar keeps my usual order under my name, so I would stop at a tenth coffee for free.", "price_floor": 3.8 }
answers/B002.json    { "id": "B002", "buys": false, "reason_code": "price", "reason": "A flat white at 4.20 is more than my usual place, and it is closer.", "price_floor": 3.2 }
answers/B003.json    { "id": "B003", "buys": true, "reason_code": "need", "reason": "Opening at seven fits my route to the station, and I order the same drink every morning.", "price_floor": 4.5 }
answers/B004.json    { "id": "B004", "buys": false, "reason_code": "trust", "reason": "I do not know the brand and nothing in the pitch tells me why I should switch.", "price_floor": 3.5 }
swarm-inbox/B005.txt Here is my answer as a buyer.
                     { "id": "B005", "buys": true, "reason_code": "habit", "reason": "Same drink, same place, most mornings: the loyalty card would pay for itself.", "price_floor": 4.2 }
swarm-inbox/B006.txt { "id": "B006", "buys": "maybe", "reason_code": "other", "reason": "I could go either way." }

Von den Briefings zur Auswertung, mit fünf von Hand geschriebenen Demonstrationsantworten
npx bmad-plus swarm briefs buyer-panel-20261019-2ftt
buyer-panel-20261019-2ftt: 30 of 30 units need a sub-agent, in waves of 10.
Wave 1:
  B001  /work/demo/app/.bmad-plus/swarm/runs/buyer-panel-20261019-2ftt/briefs/B001.md
  B002  /work/demo/app/.bmad-plus/swarm/runs/buyer-panel-20261019-2ftt/briefs/B002.md
... Einheiten B003 bis B010, dann Wellen 2 und 3 (B011 bis B030) ...
Each sub-agent: Read the brief and follow it exactly; it is your whole instruction.
Disclosure: Simulated units are not people. Read rates as an upper bound and confirm with real ones.
Vier Antwortdateien (B001 bis B004) werden nun von Hand in answers/ geschrieben.
npx bmad-plus swarm check buyer-panel-20261019-2ftt
buyer-panel-20261019-2ftt: 4 of 30 valid answers.
  B005  missing: no answer file
  B006  missing: no answer file
... und so weiter bis B030. Exit-Code 1.
npx bmad-plus swarm tally buyer-panel-20261019-2ftt
/work/demo/app/.bmad-plus/swarm/runs/buyer-panel-20261019-2ftt/tally.md
5 of 30 units counted; 25 skipped.
Disclosure: Simulated units are not people. Read rates as an upper bound and confirm with real ones.
npx bmad-plus swarm inspect buyer-panel-20261019-2ftt
buyer-panel-20261019-2ftt: tallied (panel, approved by the user)
units 30, briefed 30, valid 5, invalid 0, missing 25
Disclosure: Simulated units are not people. Read rates as an upper bound and confirm with real ones.

Ausgabe eines echten Laufs. Quelle: bmad-plus 0.23.0, 2026-10-19

tally.md (Anfang und Raten-Abschnitt)
> Simulated units are not people. Read rates as an upper bound and confirm with real ones.

# Simulated buyers see the pitch (run buyer-panel-20261019-2ftt)

5 of 30 units gave a valid answer; 25 skipped: B006 (no answer file), B007 (no answer file), ...

## Rate: buys

| group | yes | of | rate |
|---|---|---|---|
| all | 3 | 5 | 60.0% |
| segment = mid career | 2 | 4 | 50.0% |
| segment = high earner | 1 | 1 | 100.0% |
| segment = early career | 0 | 0 | n/a |
| behaviour = occasional | 1 | 3 | 33.3% |
| behaviour = daily regular | 2 | 2 | 100.0% |
| behaviour = explorer | 0 | 0 | n/a |

So liest man es: Die Rate kommt mit ihrem Nenner („3 von 5“, und 5 von 30 Einheiten gezählt), nicht als bloßer Prozentwert. Eine Gruppe ohne gültige Antwort zeigt n/a, nicht 0. Derselbe Lauf schreibt außerdem Zählungen je Begründungscode, die ersten zwei Zitate je Gruppe wörtlich sowie Median, Mittelwert, Minimum und Maximum von price_floor. Führe init mit demselben Profil, --n 30 und --seed 7 gegen einen zweiten Pitch erneut aus, um zu vergleichen: Die Datei cards.json beider Läufe ist Byte für Byte identisch (cmp meldet keinen Unterschied zwischen ihnen).

Die Schritte des Abnahmeprotokolls, erneut ausgeführt: 1 gültige Antwort von 30

Das Abnahmeprotokoll von 0.23.0 enthält einen Schwarm-Schritt in einem leeren Projekt, den eine Person durchläuft: Kein Sub-Agent läuft, der Tester ist eine Einheit, legt für B001 eine gültige Antwort ab und versucht eine schlechte. Das Werkzeug zählt genau das und sagt es. Unten dieselbe Abfolge, erneut mit der 0.23.0-CLI ausgeführt (die 30 Pfade von briefs sind gekürzt).

briefs, check, save, tally mit nur einer gültigen Antwort
npx bmad-plus swarm init --definition swarm/buyer-panel.json --profile swarm/profile.json --context pitch=swarm/pitch.md --n 30 --seed 7 --approved
buyer-panel-20261019-9da2: panel of 30 units, budget 26, approval user.
Seed 7 (same seed, same cards).
Next: bmad-plus swarm briefs buyer-panel-20261019-9da2
npx bmad-plus swarm briefs buyer-panel-20261019-9da2
buyer-panel-20261019-9da2: 30 of 30 units need a sub-agent, in waves of 10.
Wave 1:
... eine Zeile pro Einheit mit dem Briefing-Pfad, drei Wellen ...
Each sub-agent: Read the brief and follow it exactly; it is your whole instruction.
Disclosure: Simulated units are not people. Read rates as an upper bound and confirm with real ones.
Der Tester schreibt von Hand eine gültige Antwort: answers/B001.json.
npx bmad-plus swarm check buyer-panel-20261019-9da2
buyer-panel-20261019-9da2: 1 of 30 valid answers.
  B002  missing: no answer file
... B003 bis B030 ebenso.
npx bmad-plus swarm save buyer-panel-20261019-9da2 B002 --input swarm/reply-bad.txt
Swarm: Reply of unit B002 refused: field "buys" must be true or false.
swarm/reply-bad.txt enthält ein Objekt, dessen Feld buys der Text „maybe“ ist. Exit-Code 1.
npx bmad-plus swarm tally buyer-panel-20261019-9da2
/work/demo/app/.bmad-plus/swarm/runs/buyer-panel-20261019-9da2/tally.md
1 of 30 units counted; 29 skipped.
Disclosure: Simulated units are not people. Read rates as an upper bound and confirm with real ones.
head -n 3 .bmad-plus/swarm/runs/buyer-panel-20261019-9da2/tally.md
> Simulated units are not people. Read rates as an upper bound and confirm with real ones.

# Simulated buyers see the pitch (run buyer-panel-20261019-9da2)

Ausgabe eines echten Laufs. Quelle: bmad-plus 0.23.0, 2026-10-19

Eine Jury: drei Blickwinkel auf denselben Pitch

Eine Jury braucht kein Profil, kein --n und keinen Seed: Ihre Einheiten stehen in der Definition, je eine Linse. Diese (swarm/pitch-jury.json, unten samt Vorlage abgedruckt) liest denselben Pitch durch Preis, Vertrauen und Gewohnheit. Der dritte Juror trägt eine eigene id (J-habit); die ersten beiden erhalten J001 und J002 aus dem Präfix. Ihre Antwort hat nur drei Felder: ein Urteil, die schwächste Behauptung und bis zu zwei Korrekturen; die Auswertung zählt Urteile und behält die ersten drei Zitate.

swarm/pitch-jury.json (die Definition)
{
  "schemaVersion": 1,
  "id": "pitch-jury",
  "kind": "jury",
  "title": "Three lenses on the pitch",
  "units": {
    "source": "list",
    "idPrefix": "J",
    "list": [
      { "lens": "price", "stance": "Every claim is a cost the buyer pays." },
      { "lens": "trust", "stance": "Who vouches for this, and why believe them?" },
      { "id": "J-habit", "lens": "habit", "stance": "What has to change in a normal morning?" }
    ]
  },
  "brief": { "template": "briefs/juror.md", "context": ["pitch"] },
  "answer": {
    "required": ["id", "verdict", "weakest_claim"],
    "fields": {
      "verdict": { "type": "enum", "values": ["convincing", "unclear", "weak"] },
      "weakest_claim": { "type": "string", "min": 5, "max": 300 },
      "fixes": { "type": "list", "maxItems": 2 }
    }
  },
  "tally": { "counts": ["verdict"], "quotes": { "weakest_claim": 3 } },
  "disclosure": "A simulated jury is a rehearsal, not a review by the people it imitates."
}

swarm/briefs/juror.md (die Vorlage)
# Juror {{unit.id}}

Lens: {{card.lens}}. Stance: {{card.stance}}

Read the pitch below through that lens only and write a JSON object to `{{answer.path}}` with
`id` ("{{unit.id}}"), `verdict` (convincing, unclear or weak), `weakest_claim` and optional `fixes`.

{{context.pitch}}

{{disclosure}}

Die Demonstrationsantworten (answers/J001.json, answers/J002.json, answers/J-habit.json)
{ "id": "J001", "verdict": "unclear", "weakest_claim": "A flat white at 4.20 is stated, but nothing says what it is compared to.", "fixes": ["Compare the price with a nearby chain.", "Show what the loyalty card is worth in euros."] }
{ "id": "J002", "verdict": "weak", "weakest_claim": "No one vouches for the bar: there is no review, no name, no photo.", "fixes": ["Add two customer sentences with a first name."] }
{ "id": "J-habit", "verdict": "convincing", "weakest_claim": "Opening at seven is good; it does not say how long the queue is.", "fixes": ["Say how long a regular order takes."] }

Eine Jury aus drei Einheiten, mit drei von Hand geschriebenen Demonstrationsantworten
npx bmad-plus swarm init --definition swarm/pitch-jury.json --context pitch=swarm/pitch.md
pitch-jury-20261019-3qxm: jury of 3 units, budget 26, approval not-needed.
Units listed, no seed.
Next: bmad-plus swarm briefs pitch-jury-20261019-3qxm
npx bmad-plus swarm briefs pitch-jury-20261019-3qxm
pitch-jury-20261019-3qxm: 3 of 3 units need a sub-agent, in waves of 10.
Each sub-agent: Read the brief and follow it exactly; it is your whole instruction.
Disclosure: A simulated jury is a rehearsal, not a review by the people it imitates.
Drei Antwortdateien werden von Hand in answers/ geschrieben.
npx bmad-plus swarm check pitch-jury-20261019-3qxm
pitch-jury-20261019-3qxm: 3 of 3 valid answers.
npx bmad-plus swarm tally pitch-jury-20261019-3qxm
3 of 3 units counted; 0 skipped.
Disclosure: A simulated jury is a rehearsal, not a review by the people it imitates.

Ausgabe eines echten Laufs. Quelle: bmad-plus 0.23.0, 2026-10-19

tally.md der Jury
> A simulated jury is a rehearsal, not a review by the people it imitates.

# Three lenses on the pitch (run pitch-jury-20261019-3qxm)

3 of 3 units gave a valid answer; 0 skipped.

## Counts: verdict

| group | convincing | unclear | weak |
|---|---|---|---|
| all | 1 | 1 | 1 |

## Quotes: weakest_claim (up to 3 per group, verbatim)

**all**
- J001: "A flat white at 4.20 is stated, but nothing says what it is compared to."
- J002: "No one vouches for the bar: there is no review, no name, no photo."
- J-habit: "Opening at seven is good; it does not say how long the queue is."

Einsatzfälle für Panel und Jury

Welche Art welche Frage beantwortet
FrageArtWie man es startet
Schlägt der neue Pitch den alten bei denselben Leuten?panelGleiches Profil, gleiche --n und --seed; ändere nur --context pitch=...; vergleiche die beiden Auswertungen.
Welches Segment wehrt sich gegen den Preis?panelLege das Segment in groupBy, den Einwand in ein Enum-Feld und lies counts je Gruppe.
Was ist die schwächste Behauptung dieser Seite?juryEine Linse pro Juror (Preis, Vertrauen, Barrierefreiheit, Recht); lies die Zitate je Linse.
Übersteht der Plan eine kritische Gegenlesung?juryGib jedem Juror eine Haltung wie „nimm an, das scheitert; wo?“ und zähle die Urteile.
Lassen sich zwölf Seiten schreiben, ohne sich in die Quere zu kommen?fanoutEine Einheit pro Seite mit disjunktem scope; als Sitzungs-Sub-Agenten ausführen oder mit swarm plan für Nexus exportieren.

Zwei Pitches mit denselben simulierten Käufern vergleichen

Nutze es, wenn du ein Profil und eine Panel-Definition sowie zwei Textfassungen zum Testen hast. Rechne mit einer Freigabe-Rückfrage, wenn das Panel größer als 26 ist.

In deinem KI-Assistenten
Starte den Schwarm buyer-panel mit 30 Einheiten und Seed 7 auf swarm/pitch-v1.md, dann noch einmal mit demselben Seed und Profil auf swarm/pitch-v2.md. Braucht ein Lauf eine Freigabe, frage mich zuerst mit den Zahlen. Starte die Sub-Agenten Welle für Welle und antworte nie für eine Einheit. Berichte nur aus den beiden Auswertungen: zuerst der Offenlegungshinweis, dann die Kaufrate je Segment für jeden Pitch mit Nenner, die Begründungscodes und was sich zwischen beiden geändert hat.

Das solltest du erhalten Der erste init endet mit Exit-Code 2 und der Zeile „needs approval ... 30 sub-agents and the budget is 26“. Nach deinem Ja laufen drei Wellen zu je 10, check listet fehlende Einheiten, die Auswertungsdateien werden geschrieben, und der Bericht nennt den Offenlegungshinweis vor jeder Rate. Da beide Läufe Profil, --n und Seed teilen, sind ihre cards.json identisch, und der Unterschied kommt allein vom Pitch. Lies das Ergebnis als Obergrenze, die mit echten Menschen zu bestätigen ist.

Eine Jury vor dem Start eine Seite angreifen lassen

Nutze es mit einer Jury-Definition (eine Linse pro Juror) und dem zu lesenden Text als Kontextdatei. Weder Profil noch Seed sind nötig.

In deinem KI-Assistenten
Starte den Schwarm pitch-jury auf swarm/pitch.md. Ein Sub-Agent pro Juror, jeder liest nur sein eigenes Briefing. Lies jede Kontextdatei, bevor du sie übergibst. Berichte nach der Auswertung zuerst den Offenlegungshinweis, dann die Urteilszahlen und die schwächste Behauptung je Linse als Zitat und liste die von den Juroren vorgeschlagenen Korrekturen auf. Schreibe oder ändere selbst keine Antwort.

Das solltest du erhalten Drei Briefings werden gerendert, drei Sub-Agenten antworten, check meldet 3 von 3 gültigen Antworten, und tally.md beginnt mit „A simulated jury is a rehearsal, not a review by the people it imitates.“ Danach zeigt es, wie viele Juroren den Pitch überzeugend, unklar oder schwach fanden, und zitiert jede schwächste Behauptung mit der Juror-ID.

Mehrere Seiten parallel schreiben und prüfen

Nutze es, wenn Einheiten das Repository ändern, je eine Prüfung brauchen oder die Sitzung überleben müssen: exportiere den Fanout als Nexus-Plan.

In deinem KI-Assistenten
Initialisiere den Fanout site-pages aus swarm/page-fanout.json und swarm/units.json (about, pricing, contact), exportiere ihn mit swarm plan nach .bmad-plus/swarm/reports/RUN/plan.json und lege daraus den Nexus-Lauf an. Starte auf diesem Host eine Aufgabe nach der anderen, lass mich die Seite prüfen, verifiziere und akzeptiere sie dann. Akzeptiere keine Aufgabe, deren Prüfung fehlschlägt.

Das solltest du erhalten swarm plan meldet „3 tasks“ und schreibt einen Plan, dessen Aufgaben die disjunkten Scopes tragen; nexus create zeigt jede Aufgabe als „not started; verification=pending; acceptance=pending“. Pro Aufgabe: start, die Seite wird geschrieben, record, dann führt verify die Prüfung der Einheit aus und accept markiert sie als akzeptiert. Eine Aufgabe mit ungültiger Antwortdatei bleibt unakzeptiert.

Laufstruktur und Grenzen

.bmad-plus/swarm/runs/<definition-id>-<yyyymmdd>-<4 chars>/
run.json         kind, pack, hashes of every input, n, seed, wave, budget, approval, status
definition.json  the normalized definition, frozen
template.md      the brief template, frozen
cards.json       the dealt or listed units
context/<name>.md  each context file, frozen
briefs/<unit>.md   rendered by briefs or plan
answers/<unit>.json  written by the sub-agent, or filed by save
tally.json, tally.md
checks/answer.cjs, checks/swarm-validate.cjs, nexus-plan.json   (fanout, written by plan)

Grenzen
GrenzeWert
Einheiten pro Lauf1 bis 1000
budget, wave1 bis 1000 (Standard 26 und 10)
Seed0 bis 2147483647
Eingabedateien (Definition, Profil, Einheiten, Vorlage, Kontexte, Antworten)Je höchstens 16 MiB; eine an save gegebene Antwort höchstens 1 MiB
Profil10 Dimensionen mit bis zu 50 Werten, 20 Bereiche, 20 Pools mit bis zu 200 Einträgen
Antwortfelder50; Enum-Werte 50; Listenelemente bis 200; Obergrenze der Textlänge 20000
groupBy-Felder; Zitate pro Gruppe5; 1 bis 10
Fanout-Scopes pro Einheit20
Export nach NexusEine Aufgabe pro Einheit, maxParallel höchstens 32 (Nexus akzeptiert 200 Aufgaben pro Lauf)

Sicherheitsgrenzen: Die Laufzeit hat keinen Kindprozess, kein Netzwerk und kein eval; jede Datei wird atomar und nur unter .bmad-plus/swarm/ geschrieben; Pfade, die aufsteigen, absolut sind, einem Link folgen oder .git erreichen, werden abgelehnt; Eingaben werden bei init eingefroren, eine spätere Änderung eines Kontexts ändert für diesen Lauf also nichts.

Siehe auch