# SwarmForge Receive Modes Explained: Task vs Batch Processing

> Understand SwarmForge receive modes task vs batch. Learn how to process single handoffs or continuously loop for multiple handoffs in your roles.

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

---

**SwarmForge supports two receive modes—`task` and `batch`—that control whether a role processes a single handoff and exits or continuously loops to handle multiple handoffs.**

In SwarmForge (the open-source swarm orchestration framework from Robert C. Martin's repository `unclebob/swarm-forge`), receive modes determine the lifecycle behavior of roles during handoff processing. Understanding these modes is essential for designing agents that either perform one-off actions or operate as long-running workers.

---

## What Are Receive Modes in SwarmForge?

Receive modes define how a role consumes handoffs after receiving them. The mode is specified as a field in the handoff definition and is validated against a centralized set of allowed values.

In **`swarmforge/scripts/swarmforge.bb`**, the valid receive modes are declared as a Clojure set:

```clojure
(def receive-modes #{"task" "batch"})

```

This declaration at **line 145** establishes the only two valid options the system recognizes. Any handoff specifying a different mode will fail validation.

---

## Task Mode: Single-Handoff Execution

**`task` mode** instructs a role to process exactly one handoff and then complete its session. This is the default behavior when no receive mode is explicitly specified.

Use **task mode** for:

- One-off cleanup operations
- Initialization scripts
- Any role that should execute once and await explicit reactivation

The defaulting logic is implemented in **`swarmforge/scripts/handoff_lib.bb`** via the `role-receive-mode` function starting at **line 72**:

```clojure
(defn role-receive-mode [role-name]
  …)

```

When a handoff omits the receive-mode field, SwarmForge treats the role as `"task"`. This behavior is verified by the test `ready-for-next-treats-blank-receive-mode-as-task` in **`test/swarmforge/script_test.clj`** (lines 998–1012).

---

## Batch Mode: Continuous Processing Loop

**`batch` mode** keeps the role alive in a processing loop, continuously pulling and handling new handoffs without exiting after each one. The role persists until the queue empties or an external stop signal arrives.

Use **batch mode** for:

- Worker agents that consume tasks repeatedly
- Long-running processors
- Roles that must maintain state across multiple handoffs

---

## How Receive Modes Are Parsed and Validated

When SwarmForge parses a handoff definition, it examines the field immediately following the **propagation token** (e.g., `forward-only`, `back-one`, `back-all`). If this field matches a symbol in `receive-modes`, it becomes the role's configured receive mode.

Validation occurs in the `validate-window!` function in **`swarmforge/scripts/swarmforge.bb`** around **line 178**:

```clojure
(reject-if (not (#{"task" "batch"} receive-mode))
           (str "Invalid receive mode '" receive-mode "' for role '" role "' …"))

```

This strict check ensures only `"task"` or `"batch"` pass validation—any other value triggers an error with the invalid mode and role name in the message.

---

## Practical Examples

### Defining a Single-Task Role (Default)

```bash
echo "sender  receiver  master  forward-only  task  my-script.sh" > my.handoff

```

The role processes [`my-script.sh`](https://github.com/unclebob/swarm-forge/blob/main/my-script.sh) once, then stops and waits for the next explicit task assignment.

### Defining a Batch-Processing Role

```bash
echo "sender  receiver  master  forward-only  batch  my-script.sh" > my.handoff

```

The role stays alive, repeatedly invoking [`my-script.sh`](https://github.com/unclebob/swarm-forge/blob/main/my-script.sh) for each new handoff until no work remains.

### Querying Receive Mode Programmatically

```clojure
(let [mode (handoff-lib/role-receive-mode "my-role")]
  (println "Receive mode for my-role:" mode))
;; Output: "task" or "batch"

```

---

## Key Architectural Points

- **Propagation token position**: The receive mode field follows the propagation token (third field in handoff lines)
- **Session lifecycle**: Task mode ends sessions after single handoffs; batch mode persists sessions across multiple handoffs
- **Default safety**: Omitting the receive mode safely defaults to `"task"`, preventing accidental long-running processes

---

## Summary

- **SwarmForge receive modes** are strictly `"task"` or `"batch"`, defined in `swarmforge/scripts/swarmforge.bb`
- **`task` mode**: Single-handoff processing, default behavior, suitable for one-off actions
- **`batch` mode**: Continuous loop processing, explicitly set, suitable for worker agents
- **Validation**: Enforced in `validate-window!` with clear error messages for invalid modes
- **Defaulting**: `role-receive-mode` in `handoff_lib.bb` returns `"task"` when no mode is specified

---

## Frequently Asked Questions

### What happens if I specify an invalid receive mode in SwarmForge?

SwarmForge rejects the handoff with an error message. The `validate-window!` function in `swarmforge.bb` checks against the `#{"task" "batch"}` set and calls `reject-if` with a descriptive string including the invalid mode and role name.

### Can I omit the receive mode field entirely?

Yes. When the receive-mode field is blank, SwarmForge defaults to `"task"` mode. This behavior is tested in `script_test.clj` and implemented in `role-receive-mode` within `handoff_lib.bb`.

### Where is the receive mode positioned in a handoff definition?

The receive mode appears immediately after the propagation token. A complete handoff line follows this structure: `sender receiver master propagation-token receive-mode script-path`.

### Which mode should I use for a background worker that processes items continuously?

Use **`batch`** mode. This keeps the role's session alive and loops over incoming handoffs until the queue is empty or an external signal stops the process.