SwarmForge Handoff Protocol: Complete File-Based Communication System for AI Agents

The SwarmForge handoff protocol is a durable, file-based communication channel that lets AI agents exchange work-items without direct tmux socket access or manual git coordination.

The handoff protocol, as implemented in unclebob/swarm-forge, replaces legacy log-book and resend-queue mechanisms with an atomic, auditable system. Agents communicate through structured files that survive crashes and provide complete lifecycle tracking.

Core Architecture of the SwarmForge Handoff Protocol

Directory Layout and File Organization

Each agent's work-tree contains a hidden .swarmforge/handoffs/ directory with four subdirectories:

  • outbox/ — staging area for outbound handoffs
  • sent/ — archive of successfully delivered handoffs
  • failed/ — quarantine for undeliverable handoffs
  • inbox/ — incoming messages with new/, in_process/, and completed/ subfolders

The handoffd daemon watches outbox/ and copies new handoffs into recipients' inbox/new/ directories. This design, documented in swarmforge/handoff-protocol.md lines 24-38, ensures durability through simple filesystem operations.

Handoff Filename Format

Every handoff uses a strictly ordered filename that enables deterministic processing:


<priority>_<timestamp>_<seq>_from_<sender>_to_<recipients>.handoff

The sequence number guarantees total ordering when timestamps collide. Priority prefixes allow high-urgency handoffs to surface first without complex queue management.

File Structure: Headers and Body

A handoff file contains two sections separated by a blank line:

id: hand-20260615-140531-abc123
from: architect
to: cleaner
type: git_handoff
priority: 50
created_at: 2026-06-15T14:05:31Z

[opaque body content — not parsed by the system]

Critical headers (id, from, to, type) are injected by swarm_handoff.sh. The body is treated as opaque payload—agents may include shell commands, commit hashes, or free-form instructions without protocol constraints.

Supported Message Types

The protocol currently defines two message types per handoff-protocol.md lines 30-48:

Type Purpose Authorization
git_handoff Request to forward a commit to another role Automatic for role transitions
note Short free-form message Explicit authorization only

Key Components of the SwarmForge Handoff Protocol

Outbound Gate: swarm_handoff.sh

Located at swarmforge/scripts/swarm_handoff.sh, this script is the sole entry point for creating handoffs. It performs:

  1. Draft validation against protocol schema
  2. Reserved header injection (id, from, created_at)
  3. Commit hash validation (10 hexadecimal characters)
  4. Atomic write to outbox/tmp/, then rename to outbox/*.handoff

The atomic rename guarantees that handoffd never sees partially written files.

Delivery Daemon: handoffd.bb

The Babashka-based daemon (swarmforge/scripts/handoffd.bb) implements the delivery engine:

  • Scans each agent's outbox/ for new .handoff files
  • Validates file integrity and recipient existence
  • Copies to each recipient's inbox/new/ with injected recipient and enqueued_at headers
  • Sends tmux wake-up: "You have new handoff mail. If idle, run ready_for_next.sh."
  • Moves source file to sent/ on success, failed/ on error

All operations are idempotent—duplicates are detected via id header and skipped.

Queue Helper Scripts

The protocol provides abstraction scripts that shield agents from directory manipulation:

These helpers, defined in handoff-protocol.md lines 62-70, own all inbox state transitions and timestamp injection.

SwarmForge Handoff Protocol Lifecycle

Step 1: Create

Agents draft handoffs in ./tmp/ and submit via swarm_handoff.sh:


# Draft a git_handoff request

cat > ./tmp/handoff.txt <<'EOF'
type: git_handoff
to: cleaner
priority: 50
task: task-1-cave-setup
commit: a1b2c3d9e8
EOF

# Validate and queue

swarm_handoff.sh ./tmp/handoff.txt

Output: .swarmforge/handoffs/outbox/50_20260615T140531Z_000042_from_architect_to_cleaner.handoff

Step 2: Deliver

handoffd.bb detects the file, copies to recipient inbox, injects delivery metadata, and notifies via tmux. No agent action required.

Step 3: Consume

Recipient fetches work through the helper chain:

ready_for_next.sh

This reads .swarmforge/roles.tsv to determine receive mode, then executes the appropriate handler. The helper moves file(s) to inbox/in_process/ and adds dequeued_at timestamp.

Example output:


TASK: .swarmforge/handoffs/inbox/in_process/50_20260615T140531Z_000042_from_architect_to_cleaner.handoff
FROM: architect
TYPE: git_handoff
PRIORITY: 50
TASK_NAME: task-1-cave-setup
PAYLOAD:
Re-read your role and constitution.
merge_and_process.sh architect a1b2c3d9

Step 4: Complete

After work finishes:

done_with_current.sh

Updates completed_at, archives to inbox/completed/, and prints status: COMPLETED, MAIL_WAITING, or NO_TASK.

Audit Trail and Header Lifecycle

The SwarmForge handoff protocol captures complete provenance through header evolution:

Stage Header Added Script Responsible
Creation id, from, created_at, type swarm_handoff.sh
Delivery recipient, enqueued_at handoffd.bb
Consumption dequeued_at ready_for_next_*.sh
Completion completed_at done_with_current_*.sh

This immutable progression enables forensic reconstruction of any handoff's journey.

Design Goals and Protocol Guarantees

The SwarmForge handoff protocol achieves four primary objectives:

  • Durability — Handoff files survive process restarts; filesystem is the single source of truth
  • Auditability — Complete timestamp chain from creation through completion
  • Agent Simplicity — No tmux socket manipulation, no direct git operations, minimal API surface
  • Extensibility — New message types via header schema extension and daemon validation updates

Atomic operations prevent duplicate deliveries even if handoffd crashes mid-transaction. State transitions use move/rename semantics that are atomic on POSIX filesystems.

Summary

  • SwarmForge handoff protocol replaces fragile log-based coordination with durable file-system queues
  • Four directory states (outbox/, sent/, failed/, inbox/ with subfolders) provide clear handoff lifecycle management
  • swarm_handoff.sh is the only valid entry point for creating handoffs; it enforces schema and performs atomic writes
  • handoffd.bb delivers handoffs idempotently, injecting delivery metadata and sending tmux notifications
  • Helper scripts (ready_for_next.sh, done_with_current.sh) abstract queue state machines from agent logic
  • Complete audit trail through headers: created_at → enqueued_at → dequeued_at → completed_at

Frequently Asked Questions

How does the SwarmForge handoff protocol prevent duplicate deliveries?

The daemon uses the id header as a deduplication key. Before copying to any inbox, handoffd.bb checks if a handoff with that id already exists in the recipient's new/, in_process/, or completed/ folders. Combined with atomic file moves and POSIX rename semantics, this ensures exactly-once delivery semantics even across daemon restarts.

What happens if a handoff fails to deliver?

Failed deliveries move the source file from outbox/ to failed/ with an appended error reason. The original handoff remains intact for manual inspection or retry. Recipients that are temporarily unreachable do not block delivery to other recipients—each copy operation is independent.

Can agents send handoffs to multiple recipients simultaneously?

Yes. The filename to field and internal to header support comma-separated recipient lists. The daemon iterates through recipients, creating independent copies with individualized recipient headers. Each recipient receives their own enqueued_at timestamp reflecting actual delivery time.

How do agents know when new handoffs arrive?

The handoffd daemon sends a generic tmux message to the recipient's pane: "You have new handoff mail. If idle, run ready_for_next.sh." Agents poll by running ready_for_next.sh when convenient—there is no forced interrupt or callback mechanism, keeping agent logic simple and synchronous.

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 →