# SwarmForge Batch vs Task Receive Modes: How Handoff Processing Works

> Discover how SwarmForge batch vs task receive modes manage handoffs. Learn about priority-grouped batches and individual processing in this technical guide.

- Repository: [Robert C. Martin/swarm-forge](https://github.com/unclebob/swarm-forge)
- Tags: deep-dive
- Published: 2026-08-10

---

**SwarmForge uses a configurable receive mode (`task` or `batch`) defined per role in [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) to determine whether a role processes handoffs individually or as priority-grouped batches.**

The open-source SwarmForge framework (available at `unclebob/swarm-forge`) implements a sophisticated handoff protocol where each role can declare how it consumes queued work. By specifying a receive mode in the configuration, developers control whether a role handles single handoffs or aggregates equal-priority items into atomic batches.

## Configuration and Role Definition

Each role’s receive mode originates in the **swarmforge.conf** window definition. The launcher parses this configuration during project initialization and persists the normalized mode to **`.swarmforge/roles.tsv`**.

In [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf), the window syntax follows this pattern:

```text
window <role-name> <window-title> <worktree-path> <receive-mode>

```

For example, a typical role definition uses **task mode** (the default when omitted):

```text
window coder coder /path/to/coder-worktree task

```

Alternatively, roles that must process related handoffs simultaneously use **batch mode**:

```text
window cleaner cleaner /path/to/cleaner-worktree batch

```

The launcher writes these definitions to `.swarmforge/roles.tsv`, where the receive mode occupies the seventh field (index 6). According to the project's [`handoff-protocol.md`](https://github.com/unclebob/swarm-forge/blob/main/handoff-protocol.md), batch mode is recommended for roles like `cleaner`, `architect`, `hardener`, and `QA` that should consume equal-priority queued handoffs as a single unit.

## Runtime Dispatch Logic

The script **`ready_for_next.bb`** (located at `swarmforge/scripts/ready_for_next.bb`) implements the runtime decision logic. It reads the current role from the `SWARMFORGE_ROLE` environment variable, queries `.swarmforge/roles.tsv` for that role’s receive mode, and dispatches execution to the appropriate helper.

The core dispatch logic appears in the `-main` function:

```clojure
(defn receive-mode [role-name]
  (let [roles (str/split-lines (slurp (str (fs/path (project-root) ".swarmforge" "roles.tsv"))))]
    (or (some (fn [line]
                (let [fields (str/split line #"\t" -1)]
                  (when (= role-name (first fields))
                    (not-empty (get fields 6 "task")))))   ;; field 7 holds the mode
          roles)
        (exit! 1 (str "Unknown role: " role-name)))))

(defn -main []
  (case (receive-mode (role))
    "batch" (run-helper! "ready_for_next_batch.sh")
    "task"  (run-helper! "ready_for_next_task.sh")
    (exit! 2 (str "INVALID_RECEIVE_MODE: " (receive-mode (role)) " for role " (role)))))

```

This implementation ensures that SwarmForge decides at runtime whether to invoke **[`ready_for_next_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_task.sh)** or **[`ready_for_next_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_batch.sh)**, based solely on the value stored in the project’s `roles.tsv` file.

### Task Mode Processing

When `receive-mode` returns `"task"`, the system invokes **[`ready_for_next_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_task.sh)**. This helper processes exactly one handoff at a time:

- Selects the first handoff (in sorted order) from `.swarmforge/handoffs/inbox/new/`
- Moves that single handoff to `inbox/in_process/`
- Adds a `dequeued_at` timestamp
- Outputs the task details for the role to process

This mode suits roles that perform atomic operations on individual work items, such as a `coder` working on a single feature branch.

### Batch Mode Processing

When `receive-mode` returns `"batch"`, the system invokes **[`ready_for_next_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_batch.sh)**. This helper aggregates multiple handoffs into a single processing unit:

- Identifies the first handoff in `inbox/new/` to determine the target priority
- Collects all queued handoffs sharing that same priority
- Creates a unique batch directory under `inbox/in_process/`
- Moves the entire group of handoffs into that batch directory
- Timestamps all moved items and outputs batch metadata

This approach ensures that roles like `cleaner` or `QA` receive all related items of equal priority simultaneously, preventing partial processing of related handoffs.

## Completion Handling

The completion workflow mirrors the dispatch logic. The **[`done_with_current.sh`](https://github.com/unclebob/swarm-forge/blob/main/done_with_current.sh)** script reads the role’s receive mode using the same mechanism as `ready_for_next.bb`, then delegates to the appropriate completion helper:

- **[`done_with_current_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/done_with_current_task.sh)** for single handoff completion
- **[`done_with_current_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/done_with_current_batch.sh)** for batch completion

This symmetry ensures that the handoff lifecycle—from acquisition through processing to completion—respects the role’s declared receive mode consistently.

## Summary

- **SwarmForge** supports two receive modes (`task` and `batch`) configured per role in [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf)
- The launcher persists these modes to `.swarmforge/roles.tsv`, where field 7 stores the mode value
- **`ready_for_next.bb`** queries this file at runtime and dispatches to [`ready_for_next_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_task.sh) or [`ready_for_next_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_batch.sh)
- **Task mode** processes single handoffs from `inbox/new/` to `inbox/in_process/`
- **Batch mode** groups equal-priority handoffs into a dedicated batch directory under `inbox/in_process/`
- **[`done_with_current.sh`](https://github.com/unclebob/swarm-forge/blob/main/done_with_current.sh)** uses identical dispatch logic to handle completion for both modes

## Frequently Asked Questions

### What happens if I omit the receive mode in swarmforge.conf?

When omitted, the receive mode defaults to `task`. As documented in [`handoff-protocol.md`](https://github.com/unclebob/swarm-forge/blob/main/handoff-protocol.md), the system treats unspecified roles as single-handoff consumers, moving only one item at a time from the inbox to the processing directory.

### How does batch mode determine which handoffs to group together?

The [`ready_for_next_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_batch.sh) helper selects the first handoff in the sorted inbox queue to establish a priority baseline, then collects all additional handoffs in `inbox/new/` that share that exact priority value. It moves this entire cohort into a newly created batch directory under `inbox/in_process/`, ensuring atomic processing of equal-priority items.

### Can a role switch between batch and task mode dynamically?

No, the receive mode is static for the duration of a project session. The mode is read from `.swarmforge/roles.tsv` at runtime by `ready_for_next.bb`, and any changes require regenerating the roles file via the launcher. The system validates the mode string and exits with `INVALID_RECEIVE_MODE` if it encounters unrecognized values.

### Where is the receive mode documentation located?

The semantic definitions and usage recommendations for receive modes are documented in **[`swarmforge/handoff-protocol.md`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md)**. This file specifies that batch mode is intended for roles such as `cleaner`, `architect`, `hardener`, and `QA` that must consume related handoffs as a single unit rather than individually.