How the SwarmForge Daemon Validates Delivery Targets: A Complete Code Walkthrough
The SwarmForge daemon validates delivery targets by parsing the to header, checking for empty entries, banning underscores, detecting duplicates, and verifying each role exists in the repository's role definitions.
The SwarmForge daemon is responsible for routing handoff files between AI agents in a multi-agent coding workflow. Before any handoff reaches its destination, the daemon enforces strict validation rules on the delivery targets specified in the to header. This article examines the exact validation logic implemented in unclebob/swarm-forge.
The validate-recipients Function
All delivery target validation occurs in the validate-recipients function within swarmforge/scripts/swarm_handoff.bb. This function is invoked as part of the broader validate function that checks handoff headers before delivery proceeds.
The validation follows six sequential steps:
Step 1: Parse the to Header
The daemon extracts the raw string from the to header and splits it on commas to obtain individual recipient role names.
;; From swarm_handoff.bb:50
(defn validate-recipients [to]
(let [recipients (str/split to #"," -1)] ;; split on commas, keep empty
;; ... validation continues
The -1 argument to str/split preserves empty strings, enabling explicit detection of malformed entries.
Step 2: Detect Empty Recipients
If any entry is an empty string, the daemon flags an error:
;; From swarm_handoff.bb:55
(when (str/blank? recipient)
(conj errors "Header 'to' contains an empty recipient."))
This catches cases like to: "coder,,reviewer" where double commas create an empty slot.
Step 3: Disallow Underscores in Role Names
Role names may not contain underscores. This is a deliberate naming convention enforced by the protocol.
;; From swarm_handoff.bb:58
(when (str/includes? recipient "_")
(conj errors (format "Recipient role '%s' is invalid; role names may not contain underscores." recipient)))
This ensures role names use hyphens (senior-coder) rather than underscores (senior_coder).
Step 4: Detect Duplicate Recipients
The function maintains a seen set to catch repeated role names:
;; From swarm_handoff.bb:60
(when (contains? seen recipient)
(conj errors (format "Duplicate recipient '%s'." recipient)))
Duplicates are rejected even if the role is otherwise valid.
Step 5: Verify Role Existence
For every non-blank, non-duplicate role, the daemon calls role-known?—a lookup against the repository's role definitions:
;; From swarm_handoff.bb:62
(when (and (not (str/blank? recipient))
(not (role-known? recipient)))
(conj errors (format "Unknown recipient role '%s'." recipient)))
The role-known? function checks against files like roles/lieutenant.prompt to confirm the role is defined.
Step 6: Return Validated List
After processing all recipients, the function returns a vector for further handling:
;; Structure built in validate (swarm_handoff.bb:52-63)
[recipients errors] ;; extracted and wrapped in {:recipients ... :errors ...}
The parent validate function incorporates these into the overall handoff validation result.
Daemon Execution Flow
The validation hook is in swarmforge/scripts/handoffd.bb, the handoff daemon itself. The execution flow is:
- Parse handoff file → headers map
- Call
swarm-handoff/validate(which invokesvalidate-recipients) - If errors →
log!the failure and move file tofailed/ - If OK →
add-delivery-headersand copy to each recipient's inbox
Only when the recipient list passes every check does the daemon proceed with delivery.
Practical Example
;; Validating a handoff's "to" header
(require '[swarm-handoff :as sh])
(let [{:keys [recipients errors]} (sh/validate
{"type" "git_handoff"
"to" "coder,reviewer,invalid_role"}
[:type :to])]
(if (empty? errors)
(println "Delivery targets OK:" recipients)
(println "Validation failed:" errors)))
;; → Validation failed: ("Unknown recipient role 'invalid_role'.")
Multiple errors can accumulate. For example, to: "coder,_senior,coder" would produce:
"Recipient role '_senior' is invalid; role names may not contain underscores.""Duplicate recipient 'coder'."
Key Source Files
| File | Purpose |
|---|---|
swarm_handoff.bb |
Contains validate-recipients and the overall validate function |
handoffd.bb |
Daemon that reads outbound handoffs and orchestrates delivery |
[handoff-protocol.md](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md) |
Protocol specification requiring target validation |
roles/*.prompt |
Role definitions used by role-known? |
Summary
- Entry point:
validate-recipientsinswarm_handoff.bbhandles all delivery target validation - Parsing: Comma-split with empty-string preservation using
str/split - Syntax rules: No empty entries, no underscores in role names
- Semantic rules: No duplicates, all roles must be known
- Failure handling: Errors logged via
log!, handoff moved tofailed/ - Success handling:
add-delivery-headersadds recipient header and timestamps before inbox delivery
Frequently Asked Questions
What happens if a handoff has an unknown recipient role?
The daemon logs the error "Unknown recipient role 'X'." via log! in handoffd.bb, moves the handoff file to the failed/ directory, and does not attempt delivery. The handoff must be corrected and resubmitted.
Why does SwarmForge ban underscores in role names?
As enforced in swarm_handoff.bb:58, underscores are prohibited to maintain consistent naming conventions across the codebase. The protocol mandates hyphen-separated role names (senior-coder) rather than snake_case (senior_coder).
Can a handoff be delivered to multiple recipients?
Yes. The to header accepts comma-separated role names. The daemon validates each recipient independently and, if all checks pass, copies the handoff into each recipient's inbox with appropriate recipient headers added by add-delivery-headers.
Where is the role validity checked against actual role definitions?
The role-known? function performs this lookup. It references the repository's role definition files such as roles/lieutenant.prompt to confirm a role exists before permitting delivery.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →