{"slug": "building-a-signed-handoff-protocol-for-ai-coding-agents", "title": "Building a signed handoff protocol for AI coding agents", "summary": "A developer built Relay, an open-source Go daemon that creates a signed handoff protocol for AI coding agents. When an agent hits a usage limit, Relay detects the breach, requests a safe pause, snapshots the work via git, builds and signs a continuation contract, and dispatches it to the next available agent. The project aims to prevent context loss between agent sessions and is available on GitHub under Apache-2.0.", "body_md": "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.\n\nI got tired of that enough to build [Relay](https://github.com/dbisina/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.\n\nHere's what actually happens when an agent hits a wall.\n\n**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.\n\n**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:\n\n`\\`\n\n`go`\n\ntype AdapterContract interface {\n\nCapability() ProviderCapability\n\nRun(ctx, opts RunOptions, ch chan<- AgentEvent) error\n\nAwaitSafePauseWindow(ctx, breachReason string) (SafePoint, error)\n\nForceStop() error\n\n}\n\n\\`\\`\n\n**3. Snapshot.** A git commit on a dedicated session worktree branch. Your main tree is never touched, agents work in `.relay/sessions/<id>/`\n\n.\n\n**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:\n\n`\\`\n\n`json`\n\n{\n\n\"contractId\": \"c-abc123\",\n\n\"taskGoal\": \"add a refund flow to the orders service\",\n\n\"nextAction\": \"Wire POST /orders/:id/refund\",\n\n\"doNotRedo\": [\"migration 0042 applied\"],\n\n\"inFlightCode\": [{\"path\": \"orders/refund.go\", \"snippet\": \"func Refund(... // truncated\"}],\n\n\"signature\": \"hex(HMAC-SHA256(canonical JSON, signing-key))\"\n\n}\n\n\\`\\`\n\n**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.\n\n**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`\n\n), durably written to disk before each step so a crash mid-handoff just resumes where it stopped on restart.\n\nOnce the handoff is a real protocol instead of a hope, a few other things become possible:\n\n`relay detect`\n\nIt'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.\n\nGo daemon, Rust desktop app (egui), a TUI, one binary. Apache-2.0. Still early, [detect/adopt](https://github.com/dbisina/relay/discussions), 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.\n\n`\\`\n\n`bash`\n\ncurl -fsSL https://raw.githubusercontent.com/dbisina/relay/main/scripts/install.sh | bash\n\nrelay init && relay run \"add a refund flow to the orders service\"\n\n\\`\\`", "url": "https://wpnews.pro/news/building-a-signed-handoff-protocol-for-ai-coding-agents", "canonical_source": "https://dev.to/dbisina/building-a-signed-handoff-protocol-for-ai-coding-agents-37c6", "published_at": "2026-07-17 22:53:07+00:00", "updated_at": "2026-07-17 23:29:53.243044+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["Relay", "Claude Code", "Codex", "Go", "Rust", "egui", "Apache-2.0", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/building-a-signed-handoff-protocol-for-ai-coding-agents", "markdown": "https://wpnews.pro/news/building-a-signed-handoff-protocol-for-ai-coding-agents.md", "text": "https://wpnews.pro/news/building-a-signed-handoff-protocol-for-ai-coding-agents.txt", "jsonld": "https://wpnews.pro/news/building-a-signed-handoff-protocol-for-ai-coding-agents.jsonld"}}