How to Approve a Handoff in the SwarmForge Dashboard: A Complete Guide
Click the Approve button in Attention → Approvals, or POST to /api/approvals/<id>/approve to approve a handoff programmatically.
SwarmForge is an open-source AI-assisted development framework created by Uncle Bob (Robert C. Martin). Approving handoffs is a core workflow step that moves completed work between team members or AI agents. This guide covers both the dashboard UI and the underlying API implementation in the unclebob/swarm-forge repository.
Locating Pending Handoffs in the Dashboard
Pending handoffs appear in the Attention → Approvals section of the SwarmForge UI.
The dashboard structure follows this hierarchy:
#attention— the top-level gray "Attention" box#attention-approvals— pending handoffs awaiting your review#attention-clarifications— items needing additional information
Each handoff row displays:
- An "Approval" pill label
- The project and task identifier
- Documents and Approve action buttons
Reviewing Before Approval
Click the Documents button on any handoff row to inspect the associated source files. This triggers the viewDoc function defined at pack_web.bb lines 24–27.
Critical check: If the handoff has unresolved remedial comments, the Approve button will be disabled. The UI enforces this via hasRemedialComments at pack_web.bb line 7010. You must resolve all comments before proceeding.
Approving a Handoff in the UI
The approval button is created by approvalButton at pack_web.bb lines 8000–8006. When clicked:
- The handler calls
postApproval(item.id, "approve")(lines 8484–8486) - A POST request fires to the backend
loadState()refreshes the UI (lines 8485–8487)- The handoff disappears from Approvals and moves to the appropriate workflow lane
Programmatic Approval via REST API
The same endpoint powers automation and CI/CD pipelines.
# Approve a handoff by ID (replace <ID> with the actual identifier)
curl -X POST http://localhost:8000/api/approvals/<ID>/approve
The JavaScript implementation used by the dashboard:
// pack_web.bb – lines 8484-8487
async function postApproval(id, action) {
await fetch("/api/approvals/" + encodeURIComponent(id) + "/" + action, {
method: "POST"
});
loadState(); // Refresh dashboard state
}
Server-Side Approval Implementation
The backend handler resides at pack_web.bb lines 1258–1266. It delegates to the approve! helper:
;; pack_web.bb – lines 1065-1071
(defn approve! [root id]
(let [src (str (fs/path root ".swarmforge/handoffs/outbox/" id ".handoff"))
dest (str (fs/path root ".swarmforge/handoffs/outbox/" id ".handoff"))]
(spit dest (with-approved (slurp src)))))
This writes approved: true into the handoff file located at .swarmforge/handoffs/outbox/<id>.handoff.
Key Source Files
| Component | Path | Purpose |
|---|---|---|
| Dashboard HTML | swarmforge/scripts/pack/dashboard.html |
Renders the Attention → Approvals pane |
| UI Logic | swarmforge/scripts/pack_web.bb |
Button creation, comment checks, API calls |
| Approval Endpoint | swarmforge/scripts/pack_web.bb (lines 1258–1266) |
POST handler for /api/approvals/<id>/approve |
| Approval Helper | swarmforge/scripts/pack_web.bb (lines 1065–1071) |
Writes approved: true to handoff files |
| Tests | test/swarmforge/pack_ui_test.clj (lines 750–765) |
Verifies approval flow and UI updates |
Summary
- Dashboard path: Attention → Approvals → click Approve button (class
btn-approve) - API endpoint:
POST /api/approvals/<hand-off-id>/approve - Blocking condition: Unresolved remedial comments disable the Approve button
- Backend effect: Sets
approved: truein the handoff file at.swarmforge/handoffs/outbox/ - Key files:
pack_web.bbfor UI and server logic;pack/dashboard.htmlfor structure
Frequently Asked Questions
What happens if the Approve button is grayed out?
The Approve button is disabled when hasRemedialComments returns true (line 7010 in pack_web.bb). Open the Documents view, resolve all remedial comments on the handoff, and refresh the dashboard. The button will re-enable automatically.
Can I approve handoffs without using the dashboard?
Yes. Send a POST request directly to /api/approvals/<id>/approve as shown in the curl example above. This is useful for automation, scripted workflows, or integrating SwarmForge with external CI systems.
Where are approved handoffs stored?
Approved handoffs remain in .swarmforge/handoffs/outbox/ with approved: true written to the file. The dashboard filters them out of the Approvals pane after loadState() refreshes, but the files persist for audit trails.
How do I verify a handoff was actually approved?
Check the handoff file directly: cat .swarmforge/handoffs/outbox/<id>.handoff | grep approved. The line approved: true confirms approval. Alternatively, refresh the dashboard—the handoff should no longer appear in Attention → Approvals.
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 →