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

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#L24-L38). Each agent's worktree contains a hidden .swarmforge/handoffs/ directory with this hierarchy:

.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/swarmforge/scripts/swarm_handoff.sh) script handles validation and queuing:


# 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 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 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/swarmforge/scripts/ready_for_next.sh):


# 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/swarmforge/scripts/done_with_current.sh) finalizes the handoff:

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

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

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →