Minimal task handoff protocol for multi-agent coordination
Find a file
2026-02-01 09:03:08 +00:00
examples Add two-agent handoff example 2026-02-01 09:02:31 +00:00
spec Add handoff protocol JSON Schema v0.1 2026-02-01 09:01:33 +00:00
handoff.py Add reference implementation of handoff protocol 2026-02-01 09:02:14 +00:00
README.md Add comprehensive README with protocol docs and design decisions 2026-02-01 09:03:08 +00:00

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 offeredacceptedcompleted/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 → offered transition 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 context for 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_id in context to build workflows
  • Add schema validation — use jsonschema library to validate against spec/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.