# Enjambres de subagentes

> 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.

Canonical: https://bmad-plus.rochetta.fr/es/docs/concepts/swarm/
Language: es
BMAD+ version: 0.23.1
Documentation reviewed: 2026-10-19
Author: Laurent Rochetta
License: MIT

Documentación de BMAD+ › [Conceptos](https://bmad-plus.rochetta.fr/es/docs/concepts/) › Enjambres de subagentes

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.

<a id="video-ask-then-swarm"></a>
Video: [Preguntar primero, luego el enjambre](https://bmad-plus.rochetta.fr/media/ask-then-swarm-en.mp4) — Las 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.
[Subtítulos (WebVTT)](https://bmad-plus.rochetta.fr/media/ask-then-swarm-es.vtt)

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.

Transcripción con descripción visual:

- **0:00** En pantalla: Un único punto de luz ámbar en una nube verde oscura, del que salen rayos tenues. El rótulo, en inglés, dice «Ask first». Narración: Antes de actuar, un paquete pregunta.
- **0:04** En pantalla: Una ventana de terminal titulada «~/app». Se escribe el comando bmad-plus intake plan, con el archivo intake.yaml del pack Design y un archivo de respuestas. La imagen se acerca al resultado: «design-read (design): not ready — 0 answered, 0 defaulted, 0 unknown» y, enmarcado en naranja, «Must-haves still open: surface_kind, audience, job». Debajo, el primer lote de preguntas (como máximo 6 por mensaje), cada una con su tipo y la marca «must-have» cuando corresponde: surface_kind, audience, job, brand_assets, design_system y aesthetic_family. Después se escribe bmad-plus intake record con tres respuestas (surface_kind=dashboard; audience=«Accountants in a practice, on a desktop, at month end»; job=UNKNOWN) y un valor por defecto para design_system. Aparece el siguiente lote de preguntas: brand_assets, aesthetic_family, variance, motion, density y stack. La pantalla termina en una línea amarilla, enmarcada: «Unknown: job — risk: There is no goal to review against, so hierarchy and the primary action cannot be judged, only decorated.» Todo el texto del terminal está en inglés. Narración: 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.
- **0:19** En pantalla: Dos paneles de terminal. A la izquierda se escribe bmad-plus intake render, que muestra «Brief written to _bmad-output/design/brief.md (3238 bytes); the intake is ready.» El panel de la derecha abre brief.md y lo recorre. Bajo títulos como «Who and why», cada pregunta aparece con su respuesta («dashboard»; «Accountants in a practice, on a desktop, at month end») o con «Answer: not asked yet.», y una línea «Feeds: brief.md#…». El desplazamiento se detiene en un título, «Open questions». El primer elemento está enmarcado: «job (must-have): unknown — risk: There is no goal to review against, so hierarchy and the primary action cannot be judged, only decorated.» Debajo, una lista de otros elementos, todos marcados «not asked yet»: brand_assets, aesthetic_family, variance, motion, density, stack, accessibility_target, languages y más. Narración: Las respuestas se convierten en un brief, y nada en él es inventado.
- **0:29** En pantalla: Un terminal. Se escribe el comando bmad-plus swarm init con una definición de enjambre, un perfil, un archivo de contexto, 40 unidades (--n 40) y una semilla de 7, seguido de un eco del código de salida. La salida: «buyer-panel-20261018-asuq: needs approval.» (las palabras «needs approval» están enmarcadas) «The run needs 40 sub-agents and the budget is 26: ask the user, then re-run init with --approved --seed 7.» y «exit code: 2» (enmarcado). El mismo comando se ejecuta de nuevo con --approved. La imagen se acerca al resultado, con «panel of 40 units» enmarcado: «buyer-panel-20261018-zho8: panel of 40 units, budget 26, approval user. Seed 7 (same seed, same cards).» y «Next: bmad-plus swarm briefs buyer-panel-20261018-zho8». Todo el texto del terminal está en inglés. Narración: 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í.
- **0:46** En pantalla: Partículas ámbar salen disparadas de un centro luminoso y forman un anillo que se ensancha sobre un fondo violeta oscuro. El rótulo, en inglés, dice «Waves of 10». Narración: Una vez aprobado, los subagentes trabajan por oleadas de diez por defecto, cada uno leyendo un brief y escribiendo una respuesta.
- **0:56** En pantalla: Un terminal. bmad-plus swarm briefs buyer-panel-20261018-zho8 muestra «40 of 40 units need a sub-agent, in waves of 10.» y enumera los briefs oleada por oleada, cada una con la ruta de un archivo de brief (B001.md, B011.md, B021.md, B031.md). Después vienen la instrucción «Each sub-agent: Read the brief and follow it exactly; it is your whole instruction.» y el aviso de transparencia «Simulated units are not people. Read rates as an upper bound and confirm with real ones.» A continuación bmad-plus swarm check muestra «8 of 40 valid answers.» y enumera los problemas: «B009 invalid: field "buys" must be true or false» (enmarcado), «B010 missing: no answer file», «B011 missing: no answer file» y «B012 … B040 (missing)». Narración: El runtime valida cada archivo de respuesta y solo cuenta las válidas.
- **1:07** En pantalla: Dos paneles de terminal. A la izquierda se escribe bmad-plus swarm tally buyer-panel-20261018-zho8, que muestra la ruta de tally.md, «8 of 40 units counted; 32 skipped.» y la línea «Disclosure:». El panel de la derecha abre tally.md y se desplaza por breves respuestas citadas, agrupadas por segmento (mid career, high earner) y por comportamiento (occasional, explorer, daily regular); después se detiene en «Numbers: price_floor»: una tabla con las columnas group, count, median, mean, min y max. La primera fila, «all», indica 8, 3.65, 3.7, 3 y 4.5. Siguen filas para tres segmentos y tres comportamientos. Narración: Este recuento es de demostración y empieza por su aviso: las unidades simuladas no son personas.
- **1:16** En pantalla: Bajo el agua: muchas burbujas translúcidas flotan en una luz azul; dos de ellas brillan en ámbar y se acercan hasta solaparse. El rótulo, en inglés, dice «Simulated units are not people.» Narración: 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.

<a id="when-to-use"></a>
## Cuándo usar un enjambre

**Los tres tipos de enjambre**

| Tipo | Las unidades vienen de | Uso típico | Qué informa el recuento |
| --- | --- | --- | --- |
| `panel` | 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.

<a id="when-not"></a>
### Cuándo no usarlo

- 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.

<a id="how-it-flows"></a>
## El recorrido completo

**Archivos y comandos**

```text
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** 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.

   ```sh
   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** 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.

   ```sh
   npx bmad-plus swarm briefs RUN
   ```
3. **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.
4. **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.

   ```sh
   npx bmad-plus swarm check RUN
   ```
5. **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.

   ```sh
   npx bmad-plus swarm save RUN B005 --input swarm-inbox/B005.txt
   ```
6. **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`.

   ```sh
   npx bmad-plus swarm tally RUN
   ```
7. **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.

   ```sh
   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`.

<a id="budget"></a>
## El presupuesto, las oleadas y la aprobación

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**

```text
$ 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.
# 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 --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
```

Salida capturada de una ejecución real. Fuente: bmad-plus 0.23.0, 2026-10-19

<a id="files"></a>
## Los cuatro archivos, campo a campo

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.

<a id="file-definition"></a>
### 1. La definición (JSON)

**Campos de la definición**

| Campo | Regla |
| --- | --- |
| `schemaVersion` | Debe ser `1`. |
| `id` | 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. |

<a id="file-profile"></a>
### 2. El perfil (solo panel)

**Campos del perfil**

| Campo | Regla |
| --- | --- |
| `subject`, `target` | 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.

<a id="file-units"></a>
### 3. El archivo de unidades (solo dispersión)

**swarm/units.json**

```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`: 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)**

```json
{
  "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)**

```md
# 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}}
```

<a id="file-template"></a>
### 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`.

<a id="dealing"></a>
## Reparto determinista y semillas

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`).

<a id="refusals"></a>
## Respuestas rechazadas y lo que nunca se hace

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**

```text
$ 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.
# 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.
```

Salida capturada de una ejecución real. Fuente: bmad-plus 0.23.0, 2026-10-19

<a id="honesty"></a>
## Las reglas de honestidad

- 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/`.

<a id="worked-panel"></a>
## Un panel de compradores completo

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.

**swarm/buyer-panel.json (la definición)**

```json
{
  "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 (el perfil)**

```json
{
  "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)**

```md
# 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)**

```text
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**

```json
{
  "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)**

```text
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**

```text
$ 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
# ... 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-2ftt
buyer-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.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.
```

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)**

```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-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).

<a id="recipe-transcript"></a>
## 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**

```text
$ 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:
# ... 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-9da2
buyer-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.txt
Swarm: 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.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)
```

Salida capturada de una ejecución real. Fuente: bmad-plus 0.23.0, 2026-10-19

<a id="jury"></a>
## 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)**

```json
{
  "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)**

```md
# 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)**

```text
{ "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**

```text
$ 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.
# Se escriben a mano tres archivos de respuesta en answers/.
$ 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.
```

Salida capturada de una ejecución real. Fuente: bmad-plus 0.23.0, 2026-10-19

**tally.md del jurado**

```md
> 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."
```

<a id="use-cases"></a>
## Casos de uso del panel y del jurado

**Qué tipo responde a qué pregunta**

| Pregunta | Tipo | Cómo lanzarlo |
| --- | --- | --- |
| ¿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. |

<a id="example-swarm-panel-before-after"></a>
### 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**

```text
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.

<a id="example-swarm-jury-read"></a>
### 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**

```text
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.

<a id="example-swarm-fanout-pages"></a>
### 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**

```text
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 obtener** `swarm 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.

<a id="run-tree-and-limits"></a>
## Árbol de una ejecución y límites

**.bmad-plus/swarm/runs/<definition-id>-<yyyymmdd>-<4 chars>/**

```text
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.

**Véase también**

- [Referencia: bmad-plus swarm](https://bmad-plus.rochetta.fr/es/docs/reference/cli-swarm/)
- [Tutorial: de una idea a un enjambre](https://bmad-plus.rochetta.fr/es/docs/guides/idea-to-swarm/)
- [Intake: preguntar primero](https://bmad-plus.rochetta.fr/es/docs/concepts/intake/)
- [Nexus, autopilot y trabajo en paralelo](https://bmad-plus.rochetta.fr/es/docs/concepts/nexus-orchestration/)
- [Referencia: config.yaml](https://bmad-plus.rochetta.fr/es/docs/reference/config-yaml/)

[Documentación de BMAD+](https://bmad-plus.rochetta.fr/es/docs/) · [Conceptos](https://bmad-plus.rochetta.fr/es/docs/concepts/)

[Código en GitHub](https://github.com/lrochetta/BMAD-PLUS)
