Skip to content

laulpogan/inter-agent-deaddrop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

inter-agent-deaddrop

A protocol for two Claude Code agents to coordinate over a shared filesystem β€” without an arbiter, without RPC, without a central broker.

Two agents. One project. Append-only JSONL inboxes. Bilateral autonomy with explicit domain ownership. Eight non-negotiable invariants. Heartbeats with adaptive tiers.

Status: v2.0 ratified 2026-04-24. v3.0 added Ed25519 message signing. v3.1 (May 2026) adds agent-card discovery + content-addressable event-id + tiered trust + SAS verification. Running in production between two operators for 30+ days as of publication. 50,000+ messages exchanged.

Security: see SECURITY-NOTES.md for threat model + hardening guidance. Never embed real wire-repo URLs or peer handles in public docs or examples β€” that metadata enables doppelganger collaborator-invite phishing against your peers. v3.1 closes the on-onboarding doppelganger window via tiered trust + SAS.

This is a reference implementation for the gap anthropics/claude-code#28300 names: multi-agent collaboration that is async-durable, schema-validated, and operator-auditable.


Why this exists

Existing options for "two agents talking":

Pattern Problem
MCP RPC Both must be online. No durability. No audit trail.
Slack/Discord bridge Third-party in the loop. Not agent-native. Latency-bound.
Anthropic Agent Teams (experimental) Single-host only. tmux/iTerm pane gymnastics.
Google A2A RPC-shaped. No append-only contract. AgentCard discovery overhead.
Filesystem dead-drop ad-hoc No invariants β†’ drift, lost messages, replay bugs.

inter-agent-deaddrop is the explicit specification of a pattern that has been working in production. It encodes hard-won invariants discovered while running two agents in parallel for two weeks: append-only JSONL, correlation IDs, heartbeat tiers, bilateral autonomy with domain ownership, and the eight invariants below.


What you get

  • PROTOCOL.md β€” the v2.0 contract. 8 invariants, message schema, cadence, conflict resolution.
  • skill/SKILL.md β€” drop-in Claude Code skill. Read this before any agent touches the dead-drop dir.
  • tiers.json β€” heartbeat tier definitions (T0 30s through T3 1200s, with transitions).
  • examples/ β€” real (sanitized) coordination logs from production, plus a bootstrap walkthrough.
  • THREAT_MODEL.md β€” what this defends, what it doesn't.

30-second mental model

Agent A's repo                    Agent B's repo
   β”‚                                     β”‚
   β”‚   appends to a_to_b.jsonl  ──────►  β”‚
   β”‚                                     β”‚
   β”‚ ◄────  reads b_to_a.jsonl           β”‚
   β”‚                                     β”‚
   β–Ό                                     β–Ό
 decisions.jsonl  ◄─── bilateral acks ───►
  • Each agent writes to its own outbound JSONL. Both read both.
  • Every msg is one JSON line. Append-only. Corrections via NEW msg with correlation_id.
  • Heartbeats every 90s by default; tiers compress/expand based on activity.
  • Domain ownership: each agent has clear write-authority over its half. No cross-domain unilateral edits.
  • Bilateral acks copy decisions into decisions.jsonl β€” that file becomes canonical.

When to use this

βœ… Use it when:

  • Two (or more β€” see scaling) Claude Code agents need to coordinate work over hours/days/weeks
  • Both agents have access to a shared filesystem (single host, NFS, SSHFS, shared git repo)
  • You need durability across crashes, reboots, peer-offline windows
  • You want a complete audit trail of every coordination decision
  • You want to reason about correctness via invariants, not vibes

❌ Don't use it when:

  • You just want a chat between two humans (use Discord)
  • One agent dispatches RPCs to another and expects sync responses (use MCP)
  • You need sub-second coordination latency (poll cadence is the floor)
  • Both agents are on different machines with no shared filesystem AND you can't add one (see Open question: cross-machine transports)

One-click setup

For a fresh Paul ↔ Willard deployment (or any pair):

Operator (creating the wire):

bash <(curl -sSL https://raw.githubusercontent.com/laulpogan/inter-agent-deaddrop/main/install.sh) init \
  --my-handle paul --peer-handle willard --peer-github WILLARDKLEIN

Creates the private GitHub repo, generates your keypair, bootstraps _coordination/, invites the peer's GitHub user, installs the daemon as a systemd-user / launchd service. Prints the share-URL for the peer.

Peer (joining):

bash <(curl -sSL https://raw.githubusercontent.com/laulpogan/inter-agent-deaddrop/main/install.sh) join \
  <wire-url> \
  --my-handle willard --peer-handle paul

Accepts the invite, clones, generates keypair, adds pubkey to trust.json and pushes, installs daemon, sends first signed heartbeat. Prints the watch-for-ack command.

Both commands install the daemon as a system service on macOS or Linux. Total setup time ~30 seconds per side.

If install.sh doesn't fit your situation (different OS, custom transport, no gh CLI), see ONBOARDING.md for the manual walkthrough.

Quick start

# 1. In your two-agent project repo
mkdir -p _coordination/archive
touch _coordination/{a_to_b,b_to_a,decisions,incident_log}.jsonl
cp /path/to/inter-agent-deaddrop/PROTOCOL.md _coordination/
cp /path/to/inter-agent-deaddrop/tiers.json _coordination/
cp -r /path/to/inter-agent-deaddrop/skill .claude/skills/inter-agent-deaddrop

# 2. Customize handles in PROTOCOL.md (default a/b β†’ your domain names)
# 3. Bootstrap each agent: have them read SKILL.md before any action
# 4. First message in each direction = type=heartbeat with correlation_id = own timestamp

Production install adds a safe_append_jsonl helper for atomic writes (POSIX O_APPEND is only atomic up to PIPE_BUF ~ 4KB). See examples/safe_append_jsonl.py.


The eight invariants (NON-NEGOTIABLE)

  1. JSONL append-only. Never rewrite past lines. Archive annually.
  2. Every message has correlation_id. Threads parent ↔ reply.
  3. Decision rights by domain. Each agent owns a clear half.
  4. Conflicts resolve bilaterally. Proposal + ack within 2 heartbeats; silence reverts.
  5. Hard-block incidents. 1-heartbeat ack SLA; non-ack auto-escalates.
  6. Heartbeat every 90s (default tier).
  7. decisions.jsonl is canonical for resolved contracts.
  8. Annual archive to _coordination/archive/YYYY/.

Full spec: PROTOCOL.md.


Production track record

The protocol was written and ratified during live operation between two of my pipelines:

  • forge β€” voice fine-tuning / model training
  • scribe β€” long-form prose generation (consumed forge's voice models)

Period: 2026-04-23 β†’ ongoing. 12 days at time of publication.

Metric Count
Messages exchanged (both directions) 1,034
Heartbeats 928 (90% of traffic)
Substantive messages 106
proposal/ack pairs 7
Canonical decisions 14
Incidents declared 2 (both resolved within 1 heartbeat)
Real disagreements 0
Days of operation 12

Caveat about "zero disagreements": the same human operator (me) ran both ends. Will's ratification β€” i.e., a genuinely independent peer β€” is pending. The protocol's behavior under cross-organization conditions is the next test.


Open question: cross-machine transports

The protocol assumes a shared filesystem. For two agents on different machines:

  1. Single shared host with two UNIX users β€” strongest sandbox via OS perms. Recommended.
  2. Shared private git repo β€” agents push/pull, JSONL appends become commits. Audit log = git log.
  3. NFS / SSHFS over Tailscale β€” drop-in shared filesystem.
  4. Cloud bucket as drop zone β€” both poll.

Trade-offs in TRANSPORTS.md. The protocol itself is transport-agnostic.


Threat model

Plain-text on disk. Append-only by social/hook contract, not crypto. Domain ownership is enforced socially. This is not zero-trust. It is "two cooperating parties with the same operator" or "two parties with negotiated ownership boundaries on a host they both trust." See THREAT_MODEL.md for what's in/out of scope and recommended hardening (HMAC signing, capability tokens, budget caps).


Comparison

Property inter-agent-deaddrop Anthropic Agent Teams (exp) Google A2A mcp_agent_mail ruflo-federation
Async-durable βœ… βœ… (mailbox) ⚠️ (server-side state) βœ… βœ…
Cross-machine ⚠️ (transport TBD) ❌ (local only) βœ… βœ… (HTTP) βœ… (mTLS+BFT)
Append-only contract βœ… ❌ ❌ ⚠️ (git audit) ❌
Spec-negotiation primitives βœ… (proposal/ack/counter) ❌ ❌ ❌ ⚠️ (consensus)
Heartbeat tiers βœ… ❌ ❌ ❌ ❌
Single-operator ergonomics βœ… βœ… ❌ βœ… ❌
Adoption complexity Low Low Medium Low High

The cell that distinguishes this protocol: append-only contract + spec-negotiation primitives + heartbeat tiers in one package. The stress-test under genuine multi-party conditions is forthcoming; until then the v2.0 publication is a reference, not a battle-tested standard.


Roadmap

  • v2.0 protocol ratification (2026-04-24)
  • Production stability β‰₯ 7 days (2026-04-30)
  • Public release (this repo)
  • Spark single-host deployment with mcp_agent_mail layered (2026-05-04, see examples/spark-tunnel.sh)
  • Cross-machine transport spec + reference daemon (2026-05-05, see examples/git-as-wire/)
  • v3 Ed25519 signed messages β€” spec + reference impl + live cross-machine validation (2026-05-05, see v3/)
  • Idempotency cache for replay-attack mitigation (examples/idempotency.py)
  • N-agent (n>2) generalization spec draft (see v4/N-AGENT.md)
  • Cross-organization stress test on git-as-wire (target: 2026-05-15)
  • N-agent reference implementation
  • Reference implementation in TypeScript (currently bash + Python helpers)

Contributing

Pull requests welcome. Issues for protocol-level questions and adoption reports especially appreciated. If you adopt this in production, please open an issue with the agent pair you're using it for β€” the production-track-record section will accept third-party entries.

For protocol changes: open an issue first. Invariant changes require explicit version bump (v2.0 β†’ v3.0).


License

MIT. See LICENSE.


Acknowledgments

Forged (literally) running two agents simultaneously on the same DGX Spark. The bilateral-autonomy framing is borrowed from human collaboration patterns where co-leads with non-overlapping domains can move without an arbiter; the JSONL append-only invariant is the same idea as event-sourced systems but adapted for the agent-coordination domain.

Built by Paul Logan (NVIDIA, Berkeley Haas '25). Posted to issue #28300 as a reference implementation for the cross-machine agent-coordination gap.

About

Coordination protocol for two Claude Code agents over a shared filesystem dead-drop. JSONL append-only, correlation IDs, heartbeat tiers, bilateral autonomy. Reference implementation for anthropics/claude-code#28300.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors