# SwarmForge Handoff Directory Layout: A Deep Dive into the File-Based Queue System

> Explore the SwarmForge handoff directory layout at .swarmforge/handoffs/. Understand how outbound, inbound, and audit folders manage your file-based queue system for efficient message handling.

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

---

**SwarmForge stores every handoff message in a durable, file-based queue located at `.swarmforge/handoffs/` inside each agent's worktree, separating outbound messages in `outbox/` from inbound messages in `inbox/` with dedicated audit folders for sent, failed, and completed work.**

The SwarmForge handoff directory structure enables reliable inter-agent communication through atomic filesystem operations. According to the `unclebob/swarm-forge` source code, this design guarantees durability, auditability, and clear ownership boundaries between agents and the handoff daemon.

## The Core Directory Structure

The handoff layout is formally specified in [[`swarmforge/handoff-protocol.md`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md)](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L24-L38). Each agent's worktree contains a hidden `.swarmforge/handoffs/` directory with this hierarchy:

```text
.swarmforge/handoffs/
├── outbox/          # Handoffs the agent wants to send

│   └── tmp/         # Staging area for drafts (ignored by the daemon)

├── sent/            # Successfully delivered outbound handoffs

├── failed/          # Outbound handoffs that could not be delivered

└── inbox/
    ├── new/         # Incoming handoffs waiting to be processed

    ├── in_process/  # Handoffs currently being worked on

    └── completed/   # Handoffs that have been finished

```

This structure separates concerns by direction: **outbound** folders (`outbox/`, `sent/`, `failed/`) for messages the local agent originates, and **inbound** folders (`inbox/new/`, `inbox/in_process/`, `inbox/completed/`) for messages received from other agents.

## Outbound Handoff Flow

### Creating and Queueing Outbound Handoffs

Agents prepare handoffs in the staging area before atomic enqueueing. The [[`swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarm_handoff.sh)](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm_handoff.sh) script handles validation and queuing:

```bash

# Inside an agent worktree - create a draft in tmp/

echo "type: git_handoff" > ./tmp/handoff.txt
echo "to: cleaner" >> ./tmp/handoff.txt
echo "priority: 50" >> ./tmp/handoff.txt
echo "task: task-1-cave-setup" >> ./tmp/handoff.txt
echo "commit: a1b2c3d9e8" >> ./tmp/handoff.txt

# Validate and atomically move to outbox/

swarm_handoff.sh ./tmp/handoff.txt

```

The [`swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarm_handoff.sh) script performs two critical operations:
1. **Validates** the handoff file format and recipient
2. **Atomically renames** the file from `outbox/tmp/` to `outbox/`

Atomic renaming prevents partial writes from being picked up by the daemon.

### Daemon Processing and Audit Trails

The [`handoffd.bb`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/handoffd.bb) daemon watches `outbox/` and executes the delivery protocol:

1. Validates the handoff file
2. Copies it to each recipient's `inbox/new/` directory
3. Sends a tmux wake-up signal to notify the recipient
4. Moves the original file to `sent/` on success, or `failed/` on error

This provides **immutable audit trails**: `sent/` confirms delivery, while `failed/` enables retry logic or dead-letter inspection.

## Inbound Handoff Flow

### Consuming New Tasks

Agents process incoming work through helper scripts in [[`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh)](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/ready_for_next.sh):

```bash

# Single-task mode

ready_for_next.sh   # Dispatches to ready_for_next_task.sh

# Batch mode

ready_for_next_batch.sh

```

These scripts:
- Select the highest-priority file from `inbox/new/`
- **Atomically move** it to `inbox/in_process/`
- Return the file path to the caller

The atomic move prevents race conditions when multiple agent instances compete for work.

### Completing Tasks

After processing, [[`done_with_current.sh`](https://github.com/unclebob/swarm-forge/blob/main/done_with_current.sh)](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/done_with_current.sh) finalizes the handoff:

```bash
done_with_current.sh   # Dispatches to done_with_current_task.sh

# Moves file from inbox/in_process/ to inbox/completed/

```

The `inbox/completed/` folder preserves a complete processing history, enabling debugging and compliance verification.

## Design Guarantees

The SwarmForge handoff directory structure delivers three architectural properties:

- **Durability** — All state persists on disk; system crashes cannot lose pending work
- **Auditability** — `sent/`, `failed/`, and `completed/` folders provide complete handoff lifecycle visibility
- **Clear ownership** — The daemon exclusively manages `outbox/`; agents interact only with their own `inbox/` through provided scripts

This separation eliminates entire classes of coordination bugs: agents cannot accidentally corrupt the outbound queue, and the daemon never writes to inbox processing folders.

## Directory Layout Visualization

```text
$ tree -a .swarmforge/handoffs
.swarmforge/handoffs
├── outbox
│   └── tmp
├── sent
├── failed
└── inbox
    ├── new
    ├── in_process
    └── completed

8 directories, 0 files

```

## Summary

- **`.swarmforge/handoffs/`** lives in each agent's worktree as the root of all handoff state
- **`outbox/tmp/`** stages drafts before atomic enqueueing via [`swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarm_handoff.sh)
- **`outbox/`**, **`sent/`**, **`failed/`** handle outbound message lifecycle with daemon ownership
- **`inbox/new/`**, **`inbox/in_process/`**, **`inbox/completed/`** manage inbound work with agent ownership
- **Atomic file moves** at every transition guarantee consistency without locks
- **Audit folders** (`sent/`, `failed/`, `completed/`) enable operational debugging and compliance

## Frequently Asked Questions

### What happens if the handoff daemon crashes during delivery?

The daemon's atomic copy-then-move protocol ensures durability. If it crashes after copying to `inbox/new/` but before moving to `sent/`, the restart will detect the orphaned `outbox/` file and retry. Recipients may receive duplicates, which they must handle idempotently per the handoff protocol specification.

### Can multiple agent instances safely share one inbox?

Yes, through atomic filesystem operations. The [`ready_for_next_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_task.sh) helper uses atomic renames when moving files from `inbox/new/` to `inbox/in_process/`. Only one instance succeeds per file; others receive `ENOENT` and retry with the next available handoff.

### Why use a `tmp/` subdirectory instead of writing directly to `outbox/`?

The staging area prevents the daemon from observing partially-written handoffs. Agents compose multi-line handoff files incrementally; the daemon only processes complete, validated files after [`swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarm_handoff.sh) performs the atomic rename from `tmp/` to `outbox/`.

### How does SwarmForge handle handoff priority?

Files in `inbox/new/` are processed by lexical filename order. Agents encode priority in the filename prefix (e.g., `050-task-1-cave-setup.handoff` for priority 50). The `ready_for_next_*` scripts select the lexicographically first file, effectively implementing priority queue semantics without additional indexing structures.