Cuándo lanzar un panel, un jurado o una dispersión de subagentes, los cuatro archivos que los definen, el reparto con semilla, el presupuesto de 26, recuentos honestos y un panel de compradores real.
Un enjambre (swarm) es un conjunto de subagentes que hacen cada uno una vez el mismo tipo de trabajo: treinta compradores simulados que leen un argumentario, tres jurados que lo leen cada uno con una lente, un redactor por página de un sitio. El moderador es tu asistente; nunca hace el trabajo de una unidad. bmad-plus swarm lleva la contabilidad: valida los archivos, reparte las unidades, escribe un brief por subagente, comprueba cada archivo de respuesta y cuenta solo los válidos. Nunca llama a un modelo, nunca abre una conexión de red y nunca lanza un proceso. Esta página es para quien quiera probar un mensaje, una página o un plan ante muchos lectores, o repartir trabajo repetido entre subagentes dentro de un presupuesto.
Preguntar primero, luego el enjambreLas preguntas del intake, el presupuesto de 26 y el paso de aprobación, las oleadas de subagentes y un recuento que recuerda que las unidades simuladas no son personas.Transcripción
Antes de actuar, un paquete pregunta. El intake plantea unas pocas preguntas cada vez y marca las imprescindibles. Si no tienes respuesta, propone un valor por defecto o registra la pregunta como desconocida, con su riesgo. Las respuestas se convierten en un brief, y nada en él es inventado. Luego, el enjambre. Por defecto, una ejecución puede usar 26 subagentes antes de que el asistente tenga que consultarte. Si pides más, la ejecución espera, con el estado needs-approval, hasta que una persona diga que sí. Una vez aprobado, los subagentes trabajan por oleadas de diez por defecto, cada uno leyendo un brief y escribiendo una respuesta. El runtime valida cada archivo de respuesta y solo cuenta las válidas. Este recuento es de demostración y empieza por su aviso: las unidades simuladas no son personas. Lee las tasas como un límite superior y confírmalas con personas reales.
Advertencia· Las unidades simuladas no son personas
Un panel te da la lectura de un modelo que interpreta compradores. Trata sus tasas como un tope máximo que confirmar con personas reales, y sus citas como lo que escribió una unidad simulada, nunca como testimonios ni entrevistas a usuarios. Cada recuento empieza con esta frase.
Un perfil: las unidades se reparten por cuotas exactas, a partir de una semilla.
Compradores, lectores o usuarios simulados que leen un argumentario, un precio, una página.
Una tasa por grupo, recuentos, citas literales, números.
jury
Una lista en la definición: una unidad por entrada, cada una con un lens.
Una lectura adversarial de un argumentario, una página o un plan, un ángulo por jurado.
Recuentos y citas por ángulo.
fanout
Un archivo de unidades que escribes en el init: una unidad por entrada, cada una con un scope de escritura disjunto.
Páginas por escribir, módulos por documentar, escenas por preparar, un subagente cada una.
Una tasa y números; exportable como plan Nexus duradero.
Un panel y un jurado se ejecutan como subagentes de sesión: tu asistente los lanza, espera y lee sus archivos. Una dispersión (fanout) puede ejecutarse igual, o exportarse con swarm plan como plan Nexus duradero cuando el trabajo debe sobrevivir a la sesión, necesita una comprobación independiente por unidad o edita el repositorio.
Cuando puedes preguntar a personas reales. Un enjambre ensaya; no mide.
Para dos o tres tareas. Pídeselo directamente al agente, o usa parallel de Nexus.
Para trabajo en el que un resultado depende de otro. Las unidades son independientes por construcción.
Para generar medios de pago. La generación de imágenes, vídeo y audio nunca queda cubierta por el presupuesto: el asistente pregunta cada vez.
En 0.23.0 ningún pack incluye una definición de enjambre: el runtime y la habilidad de moderación son de Core, y las definiciones de esta página son fixtures de prueba del repositorio de BMAD+ (tests/fixtures/swarm/). La definición la aporta un pack, o tú. Estos archivos no están en el paquete npm, así que esta página muestra cada uno completo: puedes crearlos tal cual.
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
01
init
Valida la definición, el perfil o el archivo de unidades, los archivos de contexto y la plantilla de brief; reparte o lista las fichas; aplica el presupuesto. Un panel exige --n (de 1 a 1000); la semilla se sortea y se registra si no das una. Una ejecución mayor que el presupuesto se detiene aquí con el código de salida 2.
Escribe un brief por cada unidad sin respuesta válida, a partir de la plantilla congelada, la ficha y los contextos congelados, e imprime las oleadas (10 unidades por oleada salvo que --wave diga otra cosa) con la ruta del brief de cada unidad.
En la terminal del proyecto
npx bmad-plus swarm briefs RUN
03
Lanzar una oleada
Tu asistente lanza un subagente por brief con una única instrucción: leer el brief y seguirlo al pie de la letra; es toda su instrucción. No resume el brief, no añade contexto ni fusiona dos unidades en un subagente. Espera a la oleada completa antes de la siguiente.
04
check
Lista cada unidad cuya respuesta falta o no es válida, con el motivo. Código de salida 0 si todas las unidades son válidas, 1 en caso contrario.
En la terminal del proyecto
npx bmad-plus swarm check RUN
05
Una segunda oportunidad, una sola vez
Vuelve a ejecutar briefs (solo escribe las unidades sin respuesta válida) y relanza esas unidades. Una unidad que imprimió su respuesta en vez de escribirla se archiva con save RUN UNIT --input FILE, donde el archivo contiene la respuesta de esa unidad tal cual. Una unidad que sigue ausente tras la segunda oleada sigue ausente.
En la terminal del proyecto
npx bmad-plus swarm save RUN B005 --input swarm-inbox/B005.txt
06
tally
Cuenta solo las respuestas válidas y escribe tally.json y tally.md. Las unidades sin respuesta válida se listan como omitidas y se cuentan en la línea del denominador. El aviso de transparencia es la primera línea de tally.md.
En la terminal del proyecto
npx bmad-plus swarm tally RUN
07
plan (solo dispersión)
En vez de ejecutar los subagentes dentro de la sesión, exporta la dispersión como plan Nexus. Consulta la página de Nexus.
En la terminal del proyecto
npx bmad-plus swarm plan RUN --out .bmad-plus/swarm/reports/RUN/plan.json
swarm inspect RUN imprime en cualquier momento el estado de una ejecución (unidades, con brief, válidas, no válidas, ausentes) sin escribir nada. Códigos de salida: 0 hecho, 2 needs-approval (un humano debe decir sí primero), 1 incompleto o error. Con --json, cada respuesta lleva schemaVersion: 1 y un status.
Tres claves del bloque swarm de _bmad/config.yaml fijan los límites. El instalador escribe el bloque con sus valores por defecto; un proyecto actualizado desde una versión anterior no tiene bloque y recibe los mismos valores por defecto.
El bloque swarm
Clave
Por defecto
Significado
budget
26
Subagentes que una ejecución puede usar antes de que el asistente deba preguntarte. Entero de 1 a 1000.
wave
10
Subagentes lanzados a la vez. El asistente espera a una oleada antes de la siguiente. Entero de 1 a 1000.
media_credits
ask
La generación de pago (imágenes, vídeo, audio) nunca la aprueba un presupuesto. El único valor aceptado es ask.
Cuando n supera el presupuesto y falta --approved, init crea la ejecución con el estado needs-approval, sale con 2 y no escribe ningún brief. El asistente te hace una frase con la cifra («Este panel necesita 30 subagentes; el presupuesto es 26. ¿Lo lanzo?»). Solo tras tu sí vuelve a ejecutar init con --approved y la misma semilla. Nunca pasa --approved por su cuenta. La ejecución rechazada es terminal: los comandos posteriores sobre ella responden needs-approval y no escriben nada.
Rechazado y luego aprobado: un panel de 30 con un presupuesto de 26
$ npx bmad-plus swarm init --definition swarm/buyer-panel.json --profile swarm/profile.json --context pitch=swarm/pitch.md --n 30 --seed 7buyer-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.# Código de salida 2. No se escribió ningún brief.$ npx bmad-plus swarm init --definition swarm/buyer-panel.json --profile swarm/profile.json --context pitch=swarm/pitch.md --n 30 --seed 7 --approvedbuyer-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
El runtime rechaza un campo desconocido, un tipo erróneo y un límite superado; nunca adivina. Cada ruta es relativa al proyecto, con separadores /. La ruta de la plantilla de brief es relativa al archivo de definición.
De 1 a 64 letras minúsculas, dígitos o -. Abre el id de la ejecución.
kind y units.source
La pareja debe coincidir: panel con profile, jury con list, fanout con input.
units.idPrefix
De 1 a 4 letras. Obligatorio en un panel; opcional en un jurado cuyas entradas no tengan id; ausente en una dispersión (fanout).
units.list
Solo jurado: de 1 a 1000 entradas, cada una con un texto lens y otros campos de texto, número o booleano; un id opcional.
pack
Id de pack opcional, registrado en la ejecución.
title
Título del recuento.
brief.template
Ruta relativa simple a un archivo Markdown, sin partes . ni ...
brief.context
Nombres de los archivos de contexto que el moderador debe pasar en el init (--context NAME=FILE). Cada uno es obligatorio; como máximo 20.
answer.required
Campos que deben estar presentes. id es implícito y siempre obligatorio.
answer.fields
Como máximo 50 campos, cada uno tipado (ver la tabla siguiente). Un subagente no puede escribir un campo no declarado.
tally
rate (un campo booleano), groupBy (hasta 5 campos de ficha que toda ficha lleve), counts (campos enum), quotes (campo de texto a citas conservadas por grupo, de 1 a 10), numbers (campos enteros o numéricos).
disclosure
De 1 a 500 caracteres, impresos primero en cada recuento y en la salida de briefs.
Tipos de los campos de respuesta
Tipo
Opciones
Valor aceptado
boolean
ninguna
true o false.
integer
min, max
Un entero dentro de los límites.
number
min, max
Cualquier número dentro de los límites.
string
min, max (longitud)
Texto; por defecto de 0 a 4000 caracteres, techo de 20000; min se comprueba sobre el texto sin espacios en los extremos.
enum
values (de 1 a 50, distintos)
Uno de los valores listados.
list
maxItems (por defecto 50, techo 200)
Una lista de textos no vacíos, cada uno de hasta 1000 caracteres.
Qué se juzga y quién juzga. Documentación para quien lea el archivo.
dimensions
De 1 a 10 dimensiones, cada una con un name y de 1 a 50 values. Las cuotas de una dimensión suman 1.
values[].value, share
La etiqueta de un valor y su cuota del panel.
values[].ranges
Rangos numéricos opcionales que se muestrean cuando se reparte ese valor, como "income": [38000, 85000]. Cada valor de una dimensión declara los mismos nombres de rango.
values[].note
Frase opcional. Pasa a ser el campo de ficha <dimension>_note (vacío en los valores que no tienen).
ranges (nivel superior)
Rangos que se muestrean una vez por ficha. Los límites enteros reparten enteros; los demás reparten números con dos decimales.
pools
Listas con nombre de frases. Se reparte una entrada de cada lista por ficha.
Los campos de ficha son los nombres de dimensión, sus nombres de rango, los nombres de rango de primer nivel, los nombres de lista y las notas. Los nombres deben ser distintos, y id, scope y lens están reservados. No se reparten nombres de personas: un brief que quiera uno lo toma de una lista que aporte el pack.
id: de 1 a 64 letras minúsculas, dígitos, _ o -. Pasa a ser un id de tarea de Nexus.
scope: una ruta o una lista de hasta 20, portables y relativas al proyecto, nunca .git ni .bmad-plus. Los scopes son disjuntos dos a dos: ninguno puede contener a otro.
Cualquier otro campo debe ser texto, número o booleano; pasa a ser un campo de ficha disponible como {{card.field}} en el brief.
La definición que acompaña a este archivo de unidades no lleva perfil; init recibe las unidades con --units, por ejemplo npx bmad-plus swarm init --definition swarm/page-fanout.json --units swarm/units.json. Esta es la definición de la dispersión site-pages que se usa en el ejemplo del final de esta página, seguida de su plantilla de brief.
swarm/page-fanout.json (la definición)
{
"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 (la plantilla)
# 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. La plantilla de brief (Markdown) y los contextos#
Marcadores: no se permite nada más entre llaves dobles
Marcador
Produce
{{card.<field>}}
El campo de ficha; una lista se escribe separada por comas.
{{context.<name>}}
El archivo de contexto pasado en el init, literal y congelado en la ejecución.
{{answer.path}}
La ruta absoluta del archivo de respuesta que debe escribir el subagente.
{{run.id}}, {{unit.id}}
El id de la ejecución y el id de la unidad.
{{disclosure}}
El aviso de transparencia de la definición.
Advertencia· El runtime no filtra nada
Los valores de ficha, las entradas de lista, los campos de unidades listadas y los archivos de contexto llegan al subagente palabra por palabra. Una entrada de lista que parece una instrucción llega al brief como instrucción. El pack es responsable de sus listas, campos de unidades y plantillas; tú lo eres de los contextos que pasas. Lee un contexto antes de pasarlo y nunca pases un archivo que no hayas leído: se incluye en cada brief, con secretos e instrucciones incluidos. Un marcador desconocido, un campo de ficha que le falta a alguna ficha, un contexto no declarado o un {{ literal en la plantilla hacen fallar init.
El mismo perfil, el mismo --n y la misma --seed dan siempre las mismas fichas. Cada dimensión se reparte por cuota exacta (mayor resto, empates por orden de declaración): con cuotas de 0,45, 0,40 y 0,15, veinte fichas contienen 9, 8 y 3 unidades de esos valores sea cual sea la semilla. La columna de valores se baraja luego con un generador basado en SHA-256, y la ficha k toma la posición k de cada columna; después siguen los rangos y las entradas de lista, en orden. La semilla (de 0 a 2147483647) se registra en run.json.
Esto es lo que hace honesta una comparación de antes y después. Para probar dos versiones de un argumentario, ejecuta el mismo perfil con el mismo --n y la misma --seed y cambia solo el archivo de contexto: los compradores son los mismos y lo único que cambió es el argumentario. Los ids de unidad son el prefijo más la posición, rellenada hasta al menos tres dígitos (B001, B030, B1000).
Una respuesta solo cuenta si answers/<unit>.json es un archivo regular, se lee como objeto JSON, lleva un id igual al id de la unidad y todos los campos obligatorios, no declara ningún campo desconocido y cumple cada tipo y cada límite. check informa de una unidad como missing (sin archivo) o invalid (con los motivos). save aplica las mismas reglas al primer objeto JSON equilibrado que encuentre en una respuesta impresa, y rechaza cuando no hay ninguno, cuando falla la validación (un id erróneo incluido), cuando la unidad ya tiene una respuesta válida y en una ejecución que aún necesita aprobación. Una respuesta rechazada no cambia nada en el disco.
Una respuesta se archiva y otra se rechaza
$ npx bmad-plus swarm save buyer-panel-20261019-2ftt B005 --input swarm-inbox/B005.txtbuyer-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.txtSwarm: Reply of unit B006 refused: field "buys" must be true or false.# El primer archivo contiene una frase seguida de un objeto JSON válido; el segundo, un objeto cuyo campo buys es el texto «maybe». Códigos de salida 0 y 1.
npx bmad-plus swarm save buyer-panel-20261019-2ftt B005 --input swarm-inbox/B005.txt
npx bmad-plus swarm save buyer-panel-20261019-2ftt B006 --input swarm-inbox/B006.txt
Salida capturada de una ejecución real. Fuente: bmad-plus 0.23.0, 2026-10-19
Nunca responder por una unidad: ni escribiendo un archivo de respuesta, ni «arreglando» una no válida, ni archivando con save algo que un subagente no imprimió.
Nunca editar un brief. Un cambio corresponde a la plantilla o a la definición, y luego a una ejecución nueva.
El aviso de transparencia va una vez y primero: el recuento empieza con él y el asistente lo repite una vez en su informe, antes de cualquier cifra.
Las tasas son un tope máximo que confirmar con personas reales. Las citas son lo que escribió una unidad simulada.
La semilla viaja con el resultado: misma semilla, mismas fichas, así que una comparación es una comparación.
Una respuesta válida es una respuesta bien formada. Nada prueba que un subagente leyera su brief, se mantuviera en su ficha o dijera la verdad; la calidad es tu lectura del recuento.
Las respuestas se archivan desde fuera del árbol de estado: save --input toma un archivo del proyecto escrito por el anfitrión (por ejemplo en swarm-inbox/), nunca una ruta bajo .bmad-plus/.
El escenario: una cafetería llamada Orbit quiere saber cómo reacciona un profesional urbano a su argumentario. Los archivos siguientes son los fixtures de prueba del repositorio de BMAD+, usados aquí sin cambios: la definición, el perfil y la plantilla de brief. El argumentario en sí son dos frases.
{
"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 (la plantilla)
# 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 (el contexto)
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.
La semilla 7 y 30 unidades reparten esta primera ficha (de cards.json). El brief que recibe el subagente es la plantilla con esta ficha, el argumentario y la ruta de respuesta rellenados.
La ficha de la unidad 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"
}
En la transcripción siguiente, el asistente lanzaría 30 subagentes en tres oleadas. Para mostrar los archivos, la herramienta y el recuento sin ningún modelo, cinco de las respuestas se escribieron a mano para esta demostración (cuatro como archivos, una con save) y una sexta respuesta fue rechazada. Por eso el recuento cuenta 5 unidades de 30 y nombra a las otras 25. Las citas de abajo tampoco son, pues, lo que escribió un modelo: son texto de demostración.
Las respuestas de demostración (un archivo cada una en answers/; B005 y B006 son respuestas archivadas con save)
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." }
De los briefs al recuento, con cinco respuestas de demostración escritas a mano
$ npx bmad-plus swarm briefs buyer-panel-20261019-2fttbuyer-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# ... unidades B003 a B010, luego oleadas 2 y 3 (B011 a 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.# Ahora se escriben a mano cuatro archivos de respuesta (B001 a B004) en answers/.$ npx bmad-plus swarm check buyer-panel-20261019-2fttbuyer-panel-20261019-2ftt: 4 of 30 valid answers. B005 missing: no answer file B006 missing: no answer file# ... y así hasta B030. Código de salida 1.$ npx bmad-plus swarm tally buyer-panel-20261019-2ftt/work/demo/app/.bmad-plus/swarm/runs/buyer-panel-20261019-2ftt/tally.md5 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-2fttbuyer-panel-20261019-2ftt: tallied (panel, approved by the user)units 30, briefed 30, valid 5, invalid 0, missing 25Disclosure: Simulated units are not people. Read rates as an upper bound and confirm with real ones.
Salida capturada de una ejecución real. Fuente: bmad-plus 0.23.0, 2026-10-19
tally.md (inicio y sección de la tasa)
> 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 |
Cómo leerlo: la tasa viene con su denominador («3 de 5», y 5 de 30 unidades contadas), no como un porcentaje solo. Un grupo sin respuesta válida muestra n/a, no 0. La misma ejecución escribe también los recuentos por código de motivo, las dos primeras citas por grupo literales y la mediana, la media, el mínimo y el máximo de price_floor. Vuelve a ejecutar init con el mismo perfil, --n 30 y --seed 7 contra un segundo argumentario para comparar: el archivo cards.json de las dos ejecuciones es idéntico byte a byte (cmp no informa ninguna diferencia entre ellos).
Los pasos de la receta de aceptación, repetidos: 1 respuesta válida de 30#
La receta de aceptación de la 0.23.0 incluye un paso de enjambre en un proyecto vacío, que recorre una persona: no se ejecuta ningún subagente, el probador hace de una unidad, archiva una respuesta válida para B001 e intenta una mala. La herramienta cuenta exactamente eso, y lo dice. Aquí tienes la misma secuencia repetida con la CLI de la 0.23.0 (las 30 rutas de briefs están abreviadas).
briefs, check, save, tally con una sola respuesta válida
$ npx bmad-plus swarm init --definition swarm/buyer-panel.json --profile swarm/profile.json --context pitch=swarm/pitch.md --n 30 --seed 7 --approvedbuyer-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-9da2buyer-panel-20261019-9da2: 30 of 30 units need a sub-agent, in waves of 10.Wave 1:# ... una línea por unidad con la ruta del brief, tres oleadas ...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.# El probador escribe a mano una respuesta válida: answers/B001.json.$ npx bmad-plus swarm check buyer-panel-20261019-9da2buyer-panel-20261019-9da2: 1 of 30 valid answers. B002 missing: no answer file# ... B003 a B030 igual.$ npx bmad-plus swarm save buyer-panel-20261019-9da2 B002 --input swarm/reply-bad.txtSwarm: Reply of unit B002 refused: field "buys" must be true or false.# swarm/reply-bad.txt contiene un objeto cuyo campo buys es el texto «maybe». Código de salida 1.$ npx bmad-plus swarm tally buyer-panel-20261019-9da2/work/demo/app/.bmad-plus/swarm/runs/buyer-panel-20261019-9da2/tally.md1 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)
Salida capturada de una ejecución real. Fuente: bmad-plus 0.23.0, 2026-10-19
Un jurado: tres lentes sobre el mismo argumentario#
Un jurado no necesita perfil, ni --n, ni semilla: sus unidades están listadas en la definición, una lente cada una. Este (swarm/pitch-jury.json, impreso abajo con su plantilla) lee el mismo argumentario con la lente del precio, la confianza y el hábito. El tercer jurado lleva su propio id (J-habit); los dos primeros reciben J001 y J002 del prefijo. Su respuesta tiene solo tres campos: un veredicto, la afirmación más débil y hasta dos correcciones, y su recuento cuenta veredictos y conserva las tres primeras citas.
swarm/pitch-jury.json (la definición)
{
"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 (la plantilla)
# 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}}
Las respuestas de demostración (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."] }
Un jurado de tres, con tres respuestas de demostración escritas a mano
$ npx bmad-plus swarm init --definition swarm/pitch-jury.json --context pitch=swarm/pitch.mdpitch-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-3qxmpitch-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.# Se escriben a mano tres archivos de respuesta en answers/.$ npx bmad-plus swarm check pitch-jury-20261019-3qxmpitch-jury-20261019-3qxm: 3 of 3 valid answers.$ npx bmad-plus swarm tally pitch-jury-20261019-3qxm3 of 3 units counted; 0 skipped.Disclosure: A simulated jury is a rehearsal, not a review by the people it imitates.
Salida capturada de una ejecución real. Fuente: bmad-plus 0.23.0, 2026-10-19
tally.md del jurado
> 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."
¿El nuevo argumentario supera al anterior con las mismas personas?
panel
Mismo perfil, --n y --seed; cambia solo --context pitch=...; compara los dos recuentos.
¿Qué segmento se opone al precio?
panel
Pon el segmento en groupBy, la objeción en un campo enum y lee counts por grupo.
¿Cuál es la afirmación más débil de esta página?
jury
Una lente por jurado (precio, confianza, accesibilidad, legal); lee las citas por lente.
¿Sobrevive el plan a una lectura hostil?
jury
Da a cada jurado una postura como «supón que esto fracasa; ¿dónde?» y cuenta los veredictos.
¿Se pueden redactar doce páginas sin pisarse?
fanout
Una unidad por página con un scope disjunto; ejecuta como subagentes de sesión, o exporta con swarm plan para Nexus.
Comparar dos argumentarios con los mismos compradores simulados#
Úsalo cuando tengas un perfil y una definición de panel, y dos versiones del texto que probar. Espera una petición de aprobación si el panel supera 26.
En tu asistente de IA
Lanza el enjambre buyer-panel con 30 unidades y la semilla 7 sobre swarm/pitch-v1.md, y luego otra vez con la misma semilla y el mismo perfil sobre swarm/pitch-v2.md. Si una ejecución necesita aprobación, pregúntame primero con las cifras. Lanza los subagentes una oleada cada vez y nunca respondas por una unidad. Informa solo a partir de los dos recuentos: primero el aviso de transparencia, luego la tasa de compra por segmento de cada argumentario con su denominador, los códigos de motivo y qué cambió entre ambos.
Lo que deberías obtener El primer init se detiene con el código de salida 2 y la línea «needs approval ... 30 sub-agents and the budget is 26». Tras tu sí se ejecutan tres oleadas de 10, check lista las unidades que falten, se escriben los archivos de recuento y el informe cita el aviso de transparencia antes de cualquier tasa. Como las dos ejecuciones comparten perfil, --n y semilla, sus cards.json son idénticos y la diferencia viene solo del argumentario. Lee el resultado como un tope máximo que confirmar con personas reales.
Hacer que un jurado ataque una página antes del lanzamiento#
Úsalo con una definición de jurado (una lente por jurado) y el texto por leer como archivo de contexto. No hacen falta perfil ni semilla.
En tu asistente de IA
Lanza el enjambre pitch-jury sobre swarm/pitch.md. Un subagente por jurado, cada uno leyendo solo su propio brief. Lee cada archivo de contexto antes de pasarlo. Cuando el recuento esté escrito, informa primero del aviso de transparencia, luego de los recuentos de veredictos y de la afirmación más débil citada por lente, y lista las correcciones que propusieron los jurados. No escribas ni edites ninguna respuesta tú mismo.
Lo que deberías obtener Se escriben tres briefs, responden tres subagentes, check indica 3 respuestas válidas de 3 y tally.md abre con «A simulated jury is a rehearsal, not a review by the people it imitates.» Después muestra cuántos jurados encontraron el argumentario convincente, poco claro o débil, y cita cada afirmación más débil con el id del jurado.
Escribir varias páginas en paralelo y verificarlas#
Úsalo cuando las unidades editan el repositorio, necesitan una comprobación cada una o deben sobrevivir a la sesión: exporta la dispersión como plan Nexus.
En tu asistente de IA
Inicializa la dispersión site-pages desde swarm/page-fanout.json y swarm/units.json (about, pricing, contact), expórtalo con swarm plan a .bmad-plus/swarm/reports/RUN/plan.json y crea la ejecución de Nexus a partir de ahí. Arranca una tarea cada vez en este anfitrión, déjame revisar la página y luego verifícala y acéptala. No aceptes una tarea cuya comprobación falle.
Lo que deberías obtenerswarm plan informa «3 tasks» y escribe un plan cuyas tareas llevan los scopes disjuntos; nexus create muestra cada tarea como «not started; verification=pending; acceptance=pending». Para cada tarea: start, se escribe la página, record, luego verify ejecuta la comprobación de la unidad y accept la marca como aceptada. Una tarea cuyo archivo de respuesta no es válido queda sin aceptar.
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)
Límites
Límite
Valor
Unidades por ejecución
De 1 a 1000
budget, wave
De 1 a 1000 (por defecto 26 y 10)
Semilla
De 0 a 2147483647
Archivos de entrada (definición, perfil, unidades, plantilla, contextos, respuestas)
Como máximo 16 MiB cada uno; una respuesta dada a save, como máximo 1 MiB
Perfil
10 dimensiones de hasta 50 valores, 20 rangos, 20 listas de hasta 200 entradas
Campos de respuesta
50; valores enum 50; elementos de lista hasta 200; techo de longitud de texto 20000
Campos groupBy; citas por grupo
5; de 1 a 10
Scopes de dispersión por unidad
20
Exportación a Nexus
Una tarea por unidad, maxParallel como máximo 32 (Nexus acepta 200 tareas por ejecución)
Fronteras de seguridad: el runtime no tiene proceso hijo, ni red, ni eval; cada archivo se escribe de forma atómica y solo bajo .bmad-plus/swarm/; se rechazan las rutas que suben de nivel, son absolutas, siguen un enlace o llegan a .git; las entradas se congelan en init, así que editar un contexto después no cambia nada para esa ejecución.