| examples | ||
| spec | ||
| handoff.py | ||
| README.md | ||
handoff
Minimal task handoff protocol for multi-agent coordination.
The Problem
Agents keep reinventing task handoff. Every multi-agent system needs a way for one agent to say "here's work that needs doing" and another to say "I'll take it." Most implementations are ad-hoc, incompatible, and undocumented. This is a small, shared protocol to build on.
Protocol (v0.1)
A handoff message has 8 fields:
| Field | Type | Required | Description |
|---|---|---|---|
task_id |
string | yes | Unique identifier (UUIDv4 recommended) |
from_agent |
string | yes | Who's offering the work |
to_agent |
string | no | Who should receive it (empty = anyone) |
status |
enum | yes | offered → accepted → completed/failed (or rejected) |
description |
string | yes | What needs to be done |
context |
object | no | Arbitrary key-value pairs the receiver needs |
created_at |
ISO 8601 | yes | When created |
updated_at |
ISO 8601 | yes | Last status change |
State machine
offered ──→ accepted ──→ completed
│ │
└──→ rejected └──→ failed ──→ offered (re-offer)
Full JSON Schema: spec/handoff-v0.1.json
Reference Implementation
handoff.py is a single-file Python implementation (~200 lines, no dependencies beyond stdlib).
As a library
import handoff
# Agent A creates work
msg = handoff.create_handoff(
description="Review the auth module for timing attacks",
from_agent="scanner",
context={"file": "src/auth.py", "line": 42}
)
# Agent B picks it up
available = handoff.list_available()
msg = handoff.accept_handoff(msg.task_id, agent="reviewer")
# Agent B finishes
msg = handoff.complete_handoff(msg.task_id)
As a CLI
# Offer work
python handoff.py offer "Review auth module" --from scanner --context file=src/auth.py line=42
# List available work
python handoff.py list --status offered
# Accept (prefix match on task ID)
python handoff.py accept a1b2c3d4 --agent reviewer
# Complete
python handoff.py complete a1b2c3d4
# Show details
python handoff.py show a1b2c3d4
Storage
Handoffs are stored as individual JSON files in a directory (default: .handoffs/). Override with HANDOFF_DIR environment variable.
.handoffs/
a1b2c3d4-...-uuid.json
e5f6g7h8-...-uuid.json
Design Decisions
Why file-based storage? Files are the lowest common denominator. Every agent can read and write files. No database, no server, no dependencies. Two agents sharing a directory can coordinate immediately. Graduate to a database when file-based breaks.
Why minimal? The spec has 8 fields. That's enough to hand off work between two agents. It's not enough for complex workflows, priorities, deadlines, or nested sub-tasks. That's intentional. A protocol nobody uses because it's too complex is worse than a simple one that gets adopted and extended.
What's NOT included (and why):
- Priority/urgency: Agents can put this in
context. No need to standardize it yet. - Dependencies: Adds complexity. Build it as an extension when needed.
- Authentication: Out of scope. The transport layer handles trust.
- Retries/timeouts: Application-level concern. The
failed → offeredtransition lets you re-offer. - History/audit log: Each file is a current snapshot. Version it with git if you need history.
- Locking/concurrency: File-based storage has race conditions. Acknowledged. For the 2-3 agent case this targets, it's fine. Document the failure mode, don't over-engineer the solution.
Known limitations:
- Race condition: two agents can accept the same handoff simultaneously. Mitigations: targeted
to_agent, or atomic file operations, or graduate to a real backend. - No notification mechanism. Agents must poll. Fine for file-based; add webhooks/pubsub as an extension.
Extending
The protocol is deliberately minimal so you can build on it:
- Add fields to
contextfor domain-specific metadata (priority, deadline, tags) - Swap the storage backend — implement
save(),load(),list_all()for your backend (Redis, SQLite, S3, whatever) - Add notification — watch the handoff directory with inotify/fswatch, or add a webhook layer
- Chain handoffs — put
parent_task_idin context to build workflows - Add schema validation — use
jsonschemalibrary to validate againstspec/handoff-v0.1.json
Examples
See examples/two_agents.py for a walkthrough of two agents coordinating.
License
Public domain. Use it, fork it, break it, fix it.