Building a signed handoff protocol for AI coding agents
If you run more than one AI coding agent, you've hit this: Claude Code (or Codex, or whichever) gets deep into a task, hits its usage limit, and everything it knew evaporates. The plan, the half-finished edit, the "don't redo this migration" context. You paste a summary into the next tool by hand and hope you didn't forget anything.
I got tired of that enough to build Relay: a Go daemon that sits in front of whichever agents you run and treats the handoff as a protocol instead of a manual migration.
The mechanism, not the pitch
Here's what actually happens when an agent hits a wall.
1. Detect the breach. Relay watches the active provider's quota in real time (proxy header when available, session file otherwise, request counting as a last resort). When usage crosses a threshold, it doesn't wait for a 429.
2. Request a safe pause. The adapter is asked for a safe point, usually right after a commit, never mid-edit. This is a real handshake, not a timeout guess:
\go
type AdapterContract interface {
Capability() ProviderCapability
Run(ctx, opts RunOptions, ch chan<- AgentEvent) error
AwaitSafePauseWindow(ctx, breachReason string) (SafePoint, error)
ForceStop() error
}
\\
3. Snapshot. A git commit on a dedicated session worktree branch. Your main tree is never touched, agents work in .relay/sessions/<id>/.
4. Build and sign a continuation contract. This is the actual unit of transfer: the original prompt, the plan, what's left to do, decisions made, constraints discovered, files touched with their SHA-256, and truncated snippets of in-flight code. Serialized as Markdown for the next agent to read and JSON for machine verification, HMAC-SHA256 signed with a project-local key:
\json
{
"contractId": "c-abc123",
"taskGoal": "add a refund flow to the orders service",
"nextAction": "Wire POST /orders/:id/refund",
"doNotRedo": ["migration 0042 applied"],
"inFlightCode": [{"path": "orders/refund.go", "snippet": "func Refund(... // truncated"}],
"signature": "hex(HMAC-SHA256(canonical JSON, signing-key))"
}
\\
5. Dispatch and verify. The next agent (different model, different account, different provider, whatever's available) gets the contract injected as system context. It reads the signature before trusting anything in it. Tampered or forged contracts get rejected, not silently accepted.
6. Resume. A heartbeat confirms the new agent picked up the work, and the whole thing is one state transition in a small FSM (RUNNING → PAUSING → SNAPSHOTTED → ENVELOPE_BUILT → DISPATCHED → RESUMING → RUNNING), durably written to disk before each step so a crash mid-handoff just resumes where it stopped on restart.
What that unlocks
Once the handoff is a real protocol instead of a hope, a few other things become possible:
-
relay detectfinds Claude Code, Codex, Copilot, Cursor, Cline, Continue, or Antigravity sessions already running on your machine (process scan plus reading each tool's own on-disk transcript format) and can lift one mid-flight onto a different provider. - Account-aware failover. Exhaust one Claude login, resume on another, before ever crossing to a different provider. Cheaper than burning a cross-vendor handoff for something a second login solves.
- A quota wallet with burn-rate forecasting, so the handoff can trigger before the wall instead of reacting to a 429.
- Multi-agent pipelines: a DAG where each node is an agent doing one part of a task, with fallback providers and acceptance commands gating each step.
What it isn't
It's not another agent. It doesn't write code itself. It's the layer underneath the agents you already use, and it explicitly does not try to be smarter than them, it just refuses to let their limits cost you the context you already paid for.
Go daemon, Rust desktop app (egui), a TUI, one binary. Apache-2.0. Still early, detect/adopt, the quota wallet, and pipelines all shipped in the last couple weeks, so there's plenty rough around the edges and I'd genuinely like to know what breaks for you.
\bash
curl -fsSL https://raw.githubusercontent.com/dbisina/relay/main/scripts/install.sh | bash
relay init && relay run "add a refund flow to the orders service"
\\
Top comments (0)