# SwarmForge Handoff File Format: Complete Guide to Headers, Structure, and Naming

> Understand the SwarmForge handoff file format. Learn about headers, structure, and naming conventions for plain-text files in .swarmforge/handoffs/ to manage priority, timestamp, and routing metadata.

- Repository: [Robert C. Martin/swarm-forge](https://github.com/unclebob/swarm-forge)
- Tags: api-reference
- Published: 2026-08-11

---

**A SwarmForge handoff file is a plain-text file with a key-value header block, a blank line separator, and an opaque body, stored in `.swarmforge/handoffs/` with a lexicographically sortable filename encoding priority, timestamp, and routing metadata.**

SwarmForge implements durable inter-agent communication through a file-based handoff protocol. Each handoff is a self-contained document that agents create, queue, and process according to strict conventions defined 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). Understanding the SwarmForge handoff file format is essential for building compliant agents and debugging message flows.

## Header Block Structure

The header block contains required metadata as `key: value` pairs, one per line. According to the protocol specification [88-92](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L88-L92), the following headers are mandatory:

- `id` – unique identifier for this handoff
- `from` – role creating the handoff
- `to` – primary recipient role
- `recipient` – redundant copy for routing (matches `to` in simple cases)
- `priority` – numeric priority for queue ordering
- `type` – message type (`git_handoff` or `note`)
- `role` – role context of the sender
- `task` – associated task identifier
- `commit` – Git commit hash (for `git_handoff` type)
- `created_at` – ISO 8601 timestamp
- `enqueued_at` – timestamp when queued for delivery

Reserved headers including `completed_at`, `dequeued_at`, and `dequeued_at` must never be written by agents—these are managed exclusively by the handoff daemon or helper scripts [57-68](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L57-L68).

### Header Parsing Priority

Scripts parse authoritative metadata from headers, not from the filename [84-86](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L84-L86). This design ensures that renaming or filesystem operations cannot corrupt message routing logic.

## Body Section

After a single blank line, the **body** contains free-form text generated by the handoff daemon [90-92](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L90-L92). The body is opaque to the daemon after creation—agents may embed:

- Short instructions
- Git commands
- Multi-line notes
- Structured data (YAML, JSON, etc.)

The daemon treats everything after the first blank line as payload without interpretation.

## Filename Convention

The SwarmForge handoff filename encodes routing metadata for priority-ordered directory listing:

```

<priority>_<timestamp>_<sequence>_from_<sender>_to_<recipient-list>.handoff

```

| Component | Description |
|-----------|-------------|
| `priority` | Two-digit number `00-99` (lower = higher priority) |
| `timestamp` | UTC datetime in `YYYYMMDDTHHMMSSZ` format |
| `sequence` | Per-worktie counter for sub-second tie-breaking |
| `sender` | Role creating the handoff |
| `recipient-list` | Comma-separated targets (for audit trail) |

Example filename from the specification [63-73](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L63-L73):

```

00_20260615T140531Z_000042_from_architect_to_coder_cleaner_QA.handoff

```

This lexicographic sort order ensures that `ls` and glob patterns naturally yield priority-queued processing order.

## Complete Handoff File Example

```

id: 20260615T140531Z_000042_from_coder
from: coder
to: cleaner
recipient: cleaner
priority: 50
type: git_handoff
role: coder
task: task-1-cave-setup
commit: a1b2c3d9
created_at: 2026-06-15T14:05:31Z
enqueued_at: 2026-06-15T14:05:32Z

Re-read your role and constitution.

merge_and_process coder a1b2c3d9

```

The blank line after `enqueued_at` terminates the header; everything following is the opaque body [94-119](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L94-L119).

## Directory Layout

Handoff files traverse a defined lifecycle through subdirectories of `.swarmforge/handoffs/` [26-38](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L26-L38):

- `outbox/` – pending outbound handoffs waiting for daemon pickup
- `inbox/new/` – freshly delivered handoffs awaiting processing
- `inbox/in_process/` – handoffs currently being handled by an agent
- `inbox/completed/` – successfully processed handoffs
- `sent/` – audit copies of handoffs originated by this agent
- `failed/` – handoffs that encountered delivery or processing errors

## Working with Handoff Files

### Creating and Queuing a Handoff

Write a draft containing only user-supplied headers, then use [`swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarm_handoff.sh) to validate and generate the complete file:

```bash

# Create a draft handoff (header section only)

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

# Validate and queue – script generates id, timestamps, and filename

swarm_handoff.sh /tmp/draft.handoff

# Result: .swarmforge/handoffs/outbox/50_20231102T123045Z_000001_from_coder_to_cleaner.handoff

```

### Inspecting Received Handoffs

Extract just the header portion for quick inspection:

```bash
head -n 12 .swarmforge/handoffs/inbox/new/50_20231102T123045Z_000001_from_coder_to_cleaner.handoff

```

### Parsing Headers Programmatically

The test suite in [`test/swarmforge/handoff_test.clj`](https://github.com/unclebob/swarm-forge/blob/main/test/swarmforge/handoff_test.clj) demonstrates robust header parsing:

```clojure
(require '[clojure.java.io :as io])

(defn parse-headers [path]
  (with-open [r (io/reader path)]
    (->> (line-seq r)
         (take-while (complement clojure.string/blank?))
         (map #(clojure.string/split % #":\s+" 2))
         (into {}))))

(parse-headers ".swarmforge/handoffs/inbox/new/50_20231102T123045Z_000001_from_coder_to_cleaner.handoff")
;; => {"id" "20231102T123045Z_000001_from_coder", "from" "coder", ...}

```

## Key Implementation Files

| File | Purpose |
|------|---------|
| [[`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) | Canonical specification of format, naming, and lifecycle |
| [[`swarmforge/scripts/swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm_handoff.sh)](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm_handoff.sh) | Validates drafts and writes complete handoff files |
| [`swarmforge/scripts/handoffd.bb`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/handoffd.bb) | Daemon for delivery and audit header management |
| [`test/swarmforge/handoff_test.clj`](https://github.com/unclebob/swarm-forge/blob/main/test/swarmforge/handoff_test.clj) | Conformance tests for parsing and handling |

## Message Types

The SwarmForge handoff file format supports two primary message types [27-33](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L27-33):

- **`git_handoff`** – Transfers a Git commit hash between roles, typically accompanied by processing instructions in the body
- **`note`** – Short free-form messages without commit references

Both types share identical header structure and filename conventions.

## Summary

- SwarmForge handoff files are plain-text documents with `key: value` headers, a blank separator, and an opaque body
- **Filenames encode priority and routing** using a sortable format: `priority_timestamp_sequence_from_sender_to_recipients.handoff`
- **Headers are authoritative**—scripts ignore filename metadata for critical routing decisions
- The **handoff daemon** manages reserved headers like `completed_at`; agents must never write these
- **Two message types** (`git_handoff`, `note`) support commit handoffs and unstructured communication
- Files lifecycle through `.swarmforge/handoffs/` subdirectories: `outbox` → `inbox/new` → `inbox/in_process` → `inbox/completed`

## Frequently Asked Questions

### What happens if an agent writes a reserved header?

Reserved headers such as `completed_at`, `dequeued_at`, and `enqueued_at` are managed exclusively by the handoff daemon and helper scripts. According to the protocol specification [57-68](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L57-68), agents that write these headers violate the contract and may cause routing or audit failures. The [`swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarm_handoff.sh) script prevents this by only allowing agent-supplied headers in draft files.

### How does SwarmForge ensure handoffs process in priority order?

The **filename convention** guarantees lexicographic sort order matches priority order. Filenames begin with a two-digit priority (`00-99`), followed by timestamp and sequence. Lower numeric priority values indicate higher urgency. When agents or the daemon list directory contents, the natural sort order yields correct processing sequence without additional indexing.

### Can the handoff body contain structured data?

Yes. The body is **opaque to the daemon** after creation [90-92](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L90-92). Agents may embed JSON, YAML, shell commands, or plain text instructions. The daemon copies the body unchanged during delivery. Recipients are responsible for parsing body content according to their agreed protocols—typically `git_handoff` bodies contain Git commands and `note` bodies contain human-readable instructions.

### What creates the sequence number in filenames?

The **per-worktree counter** in [`swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarm_handoff.sh) generates sequence numbers [63-73](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md#L63-73). This six-digit zero-padded number ensures unique filenames when multiple handoffs share the same timestamp second. The counter persists in the worktree state and increments atomically to prevent collisions during high-throughput scenarios.